자바 상속 마스터하기: 서브클래싱과 슈퍼클래스 원리
상속은 한 클래스가 다른 클래스의 속성(메서드와 필드)을 획득하는 과정으로 정의할 수 있습니다. 상속을 사용하면 정보를 계층적 순서로 관리하기 쉽게 만듭니다.
다른 클래스의 속성을 상속받는 클래스를 서브클래스(subclass, 파생 클래스, 자식 클래스), 속성이 상속되는 클래스를 슈퍼클래스(superclass, 베이스 클래스, 부모 클래스)라고 합니다.
extends 키워드
extends는 클래스의 속성을 상속받는 데 사용되는 키워드입니다. extends 키워드 구문은 다음과 같습니다.
구문
class Super {
.....
.....
}
class Sub extends Super {
.....
.....
}
샘플 코드
자바 상속을 시연하는 예제입니다. Calculation과 My_Calculation 두 클래스가 있습니다.
extends 키워드를 사용하여 My_Calculation이 Calculation 클래스의 addition()과 Subtraction() 메서드를 상속받습니다.
다음 프로그램을 My_Calculation.java 파일명으로 복사해 붙여넣기 하세요.
예제
class Calculation {
int z;
public void addition(int x, int y) {
z = x + y;
System.out.println("The sum of the given numbers: " + z);
}
public void Subtraction(int x, int y) {
z = x - y;
System.out.println("The difference between the given numbers: " + z);
}
}
public class My_Calculation extends Calculation {
public void multiplication(int x, int y) {
z = x * y;
System.out.println("The product of the given numbers: " + z);
}
public static void main(String args[]) {
int a = 20, b = 10;
My_Calculation demo = new My_Calculation();
demo.addition(a, b);
demo.Subtraction(a, b);
demo.multiplication(a, b);
}
}
다음과 같이 컴파일하고 실행하세요.
javac My_Calculation.java
java My_Calculation
프로그램 실행 후 결과:
출력
The sum of the given numbers: 30
The difference between the given numbers: 10
The product of the given numbers: 200
위 프로그램에서 My_Calculation 클래스 객체가 생성되면 슈퍼클래스의 내용 복사본이 그 안에 만들어집니다. 그래서 서브클래스 객체를 사용하여 슈퍼클래스 멤버에 접근할 수 있습니다.
슈퍼클래스 참조 변수는 서브클래스 객체를 담을 수 있지만, 그 변수로는 슈퍼클래스 멤버만 접근할 수 있습니다. 따라서 두 클래스 멤버 모두에 접근하려면 항상 서브클래스 타입의 참조 변수를 생성하는 것이 좋습니다.
위 프로그램을 고려하면 다음과 같이 인스턴스화할 수 있습니다. 하지만 슈퍼클래스 참조 변수(cal인 경우)를 사용하면 서브클래스 My_Calculation에 속한 multiplication() 메서드를 호출할 수 없습니다.
Calculation demo = new My_Calculation();
demo.addition(a, b);
demo.Subtraction(a, b);
참고 - 서브클래스는 슈퍼클래스의 모든 멤버(필드, 메서드, 중첩 클래스)를 상속받습니다. 생성자는 멤버가 아니므로 서브클래스에 상속되지 않지만, 슈퍼클래스 생성자는 서브클래스에서 호출할 수 있습니다.
super 키워드
super 키워드는 this 키워드와 유사합니다. super 키워드가 사용되는 시나리오는 다음과 같습니다.
- 슈퍼클래스 멤버와 서브클래스 멤버의 이름이 같을 때 구별하기 위해
- 서브클래스에서 슈퍼클래스 생성자 호출하기 위해
멤버 구별하기
한 클래스가 다른 클래스의 속성을 상속받는데, 슈퍼클래스 멤버 이름이 서브클래스와 같다면 super 키워드로 구별합니다.
super.variable
super.method();
샘플 코드
super 키워드 사용법을 시연하는 프로그램입니다.
두 클래스 Sub_class와 Super_class가 있는데, 둘 다 display() 메서드(구현 다름)와 num 변수(값 다름)를 가집니다. 두 클래스의 display() 메서드를 호출하고 두 클래스의 num 변수 값을 출력합니다. super 키워드로 슈퍼클래스 멤버와 서브클래스 멤버를 구별하는 것을 볼 수 있습니다.
프로그램을 Sub_class.java 파일명으로 복사해 붙여넣기 하세요.
예제
class Super_class {
int num = 20;
// 슈퍼클래스의 display 메서드
public void display() {
System.out.println("This is the display method of superclass");
}
}
public class Sub_class extends Super_class {
int num = 10;
// 서브클래스의 display 메서드
public void display() {
System.out.println("This is the display method of subclass");
}
public void my_method() {
// 서브클래스 인스턴스화
Sub_class sub = new Sub_class();
// 서브클래스의 display() 메서드 호출
sub.display();
// 슈퍼클래스의 display() 메서드 호출
super.display();
// 서브클래스의 num 변수 값 출력
System.out.println("value of the variable named num in sub class: " + sub.num);
// 슈퍼클래스의 num 변수 값 출력
System.out.println("value of the variable named num in super class: " + super.num);
}
public static void main(String args[]) {
Sub_class obj = new Sub_class();
obj.my_method();
}
}
다음 구문으로 컴파일하고 실행하세요.
javac Sub_class.java
java Sub_class
프로그램 실행 결과:
출력
This is the display method of subclass
This is the display method of superclass
value of the variable named num in sub class: 10
value of the variable named num in super class: 20
슈퍼클래스 생성자 호출하기
한 클래스가 다른 클래스의 속성을 상속받으면 서브클래스는 자동으로 슈퍼클래스의 기본 생성자를 획득합니다. 하지만 슈퍼클래스의 매개변수 있는 생성자를 호출하려면 super 키워드를 사용해야 합니다.
super(values);
샘플 코드
슈퍼클래스의 매개변수 있는 생성자를 호출하기 위해 super 키워드를 사용하는 방법을 시연합니다. 이 프로그램은 슈퍼클래스와 서브클래스를 포함하며, 슈퍼클래스는 정수 값을 받는 매개변수 있는 생성자를 가지고 있고, super 키워드로 이를 호출합니다.
다음 프로그램을 Subclass.java 파일명으로 복사해 붙여넣기 하세요.
예제
class Superclass {
int age;
Superclass(int age) {
this.age = age;
}
public void getAge() {
System.out.println("The value of the variable named age in super class is: " + age);
}
}
public class Subclass extends Superclass {
Subclass(int age) {
super(age);
}
public static void main(String args[]) {
Subclass s = new Subclass(24);
s.getAge();
}
}
다음 구문으로 컴파일하고 실행하세요.
javac Subclass.java
java Subclass
프로그램 실행 결과:
출력
The value of the variable named age in super class is: 24
IS-A 관계
IS-A는 "이 객체는 저 객체의 한 종류다"라고 말하는 방식입니다. extends 키워드가 상속을 달성하는 데 어떻게 사용되는지 봅시다.
public class Animal { }
public class Mammal extends Animal { }
public class Reptile extends Animal { }
public class Dog extends Mammal { }
위 예제를 바탕으로 객체지향 관점에서 다음이 참입니다.
- Animal은 Mammal 클래스의 슈퍼클래스
- Animal은 Reptile 클래스의 슈퍼클래스
- Mammal과 Reptile은 Animal 클래스의 서브클래스
- Dog는 Mammal과 Animal 클래스 모두의 서브클래스
IS-A 관계를 고려하면:
- Mammal IS-A Animal
- Reptile IS-A Animal
- Dog IS-A Mammal
- 따라서: Dog IS-A Animal이기도 함
extends 키워드 사용으로 서브클래스는 슈퍼클래스의 private 속성을 제외한 모든 속성을 상속받습니다.
instanceof 연산자로 Mammal이 실제로 Animal인지 확인할 수 있습니다.
예제
class Animal { }
class Mammal extends Animal { }
class Reptile extends Animal { }
public class Dog extends Mammal {
public static void main(String args[]) {
Animal a = new Animal();
Mammal m = new Mammal();
Dog d = new Dog();
System.out.println(m instanceof Animal);
System.out.println(d instanceof Mammal);
System.out.println(d instanceof Animal);
}
}
실행 결과
true
true
true
extends 키워드를 잘 이해했으니, implements 키워드가 IS-A 관계를 얻는 데 어떻게 사용되는지 봅시다.
일반적으로 implements 키워드는 인터페이스의 속성을 상속받기 위해 클래스와 함께 사용됩니다. 인터페이스는 클래스에 의해 확장될 수 없습니다.
예제
public interface Animal { }
public class Mammal implements Animal { }
public class Dog extends Mammal { }
instanceof 키워드
instanceof 연산자를 사용하여 Mammal이 실제로 Animal인지, Dog가 실제로 Animal인지 확인해 봅시다.
예제
interface Animal { }
class Mammal implements Animal { }
public class Dog extends Mammal {
public static void main(String args[]) {
Mammal m = new Mammal();
Dog d = new Dog();
System.out.println(m instanceof Animal);
System.out.println(d instanceof Mammal);
System.out.println(d instanceof Animal);
}
}
실행 결과
true
true
true
HAS-A 관계
이 관계들은 주로 사용법을 기반으로 합니다. 어떤 클래스가 특정 것을 HAS-A하는지 결정합니다. 이 관계는 코드 중복과 버그를 줄이는 데 도움이 됩니다.
예제를 봅시다.
예제
public class Vehicle { }
public class Speed { }
public class Van extends Vehicle {
private Speed sp;
}
이는 Van 클래스가 Speed를 HAS-A함을 보여줍니다. Speed를 별도 클래스로 두면 Van 클래스 안에 속도 관련 코드를 모두 넣지 않아도 되어, Speed 클래스를 여러 애플리케이션에서 재사용할 수 있습니다.
객체지향 특성에서 사용자는 어떤 객체가 실제 작업을 수행하는지 알 필요가 없습니다. 이를 위해 Van 클래스는 Van 클래스 사용자로부터 구현 세부사항을 숨깁니다. 기본적으로 사용자는 Van 클래스에게 특정 동작을 요청하고, Van 클래스는 스스로 작업을 수행하거나 다른 클래스에게 작업을 요청합니다.
상속의 종류
아래와 같이 다양한 상속 유형이 있습니다.
매우 중요한 사실: 자바는 다중 상속을 지원하지 않습니다. 즉, 한 클래스가 두 개 이상의 클래스를 확장할 수 없습니다. 따라서 다음은 불법입니다.
public class extends Animal, Mammal { }
그러나 클래스는 하나 이상의 인터페이스를 구현할 수 있으며, 이는 자바가 다중 상속의 불가능성을 극복하는 데 도움이 되었습니다.