import와 상속관계, overriding, super 키워드 등 상속의 기초적인 개념에 대해 이해함
스파르타 자바 문법 총정리 3 - 10 ~ 3 - 14의 내용을 기반으로 학습함
일요일 스터디는 쉬는걸로 ;)
다들 즐거운 휴일 보내세요 🙂
재충전 하고 오세용
김근보 5
김은양 2
신동현 4
장기웅 3
고예진 1
“자바스터디”라는 패키지에 “사전준비”라는 패키지가 있고 그 안에 “사전질문”이라는 클래스가 있을 때 “사전질문” 클래스를 이용하고 싶습니다. import를 이용해 알맞게 경로를 입력 해 주세요.
import javastudy.preliminary.preliminary;
자바스터디 패키지. 사전준비 패키지. 사전질문 클래스;
public class Answer {
}
package javastudy.preliminary;
자바스터디 패키지. 사전준비 패키지;
public class Answer {
}
class Animal {
public void sound() {
System.out.println("동물의 소리");
}
}
class Dog extends Animal {
public void sound() {
System.out.println("멍멍");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Animal();
animal.sound();
Dog dog = new Dog();
dog.sound();
Animal animal2 = new Dog();
animal2.sound();
}
}
Animal animal = new Animal();
animal.sound();
Animal 클래스의 sound 메소드를 호출 “동물의 소리”Dog dog = new Dog();
dog.sound();
Dog 클래스의 sound 메소드 호출 “멍멍”Animal animal2 = new Dog();
animal2.sound();
Dog 클래스의 부모 클래스인 Animal 클래스의 sound 호출 “동물의 소리”Animal animal2 = new Dog();
animal2.sound();
Dog 클래스의 부모 클래스인 Animal 클래스의 sound 호출 “동물의 소리”이지만 현재 overriding으로 인해 실제 출력은 “멍멍”Animal animal2 = new Dog();
해당 객체는 부모 클래스의 메서드만을 사용할 수 있지만 부모 클래스의 메서드를 자식 클래스에서 오버라이딩 했다면 자식 클래스에서 오버라이딩 한 메서드를 호출할 수 있다. 간단히 다시 말 하자면 부모 클래스에만 있는 메서드와 오버라이딩 된 자식 클래스의 메서드만을 사용할 수 있게 되는 것이다. 때문에 animal2에서 sound를 호출하면 오버라이딩 된 sound가 호출된다.클래스 A는 변수 a와 메서드 methodA를 가지고 있습니다. 클래스 B는 클래스 A를 상속받고, 변수 b와 메서드 methodB를 가지고 있습니다. 클래스 C는 변수 c와 클래스 A를 포함하고 있습니다. 클래스 D는 클래스 B를 상속받고, 메서드 methodD를 가지고 있습니다. 그리고,
클래스 A의 인스턴스를 생성하고, 이를 변수 a에 저장합니다.
클래스 B의 인스턴스를 생성하고, 이를 변수 b에 저장합니다.
클래스 C의 인스턴스를 생성하고, 이를 변수 c에 저장합니다.
클래스 D의 인스턴스를 생성하고, 이를 변수 d에 저장합니다.
가능하다 : class B는 class A를 상속 받고 있기 때문에 변수 b를 a에 저장가능하다.
불가능하다 : class C는 class A 포함하지만, class B 와는 아무 관계가 아니기 때문에, 즉 상속을 받지 않기 때문에 불가능하다.
class B를 상속받고 그 B는 class A를 상속 받고 있기 때문에 A와 B 클래스 모두를 상속 받는 것과 같다.
class B 와 class A의 변수와 메소드 모두 사용가능
아니요.
변수 a는 C타입으로 만든 객체에 참조변수 c를 저장할 수 있나?
class c는 class A를 포함하고 있지만 상속은 아니 때문에 A는 c에 저장 될 수 없다.
A 클래스의 인스턴스는 C클래스안에 존재할 뿐 상속은 아니라서 불가능하다.
public final class Car {}
...
public class Bus extends Car{} // 오류
// 부모 클래스 Car 생성자
public Car(String model, String color, double price) {
this.model = model;
this.color = color;
this.price = price;
}
// 자식 클래스 SportsCar 생성자
public SportsCar(String model, String color, double price, String engine) {
super.model = model; //해당 코드
super.color = color; //해당 코드
super.price = price; //해당 코드
this.engine = engine;
}
표시 해 놓은 세 줄의 코드를 한 줄로 줄이세요.
super(model, color, price);
위 코드는 Car 클래스의 생성자를 호출하여 model, color, price 를 전달해 Car클래스의 필드를 초기화 하고 있다. super 키워드를 사용하면 부모 클래스의 생성자를 호출할 때, 인자로 전달하는 값을 바로 부모 클래스의 필드에 할당할 수 있다. (부모 클래스의 생성자가 부모 클래스의 필드를 초기화하는 역할을 수행하기 때문에) 정답 : super 를 사용하여 한 번에 모든 부모 클래스의 필드를 초기화할 수 있기 때문에 한줄로 쓸 수 있다. 사용이유 : super는 자식클래스에서 부모 클래스의 멤버(필드, 메서드, 생성자)를 참조하기 위해 사용한다. 주의사항 : 자식 클래스의 생성자에서 super 키워드를 사용하여 부모 클래스의 생성자를 호출하면, 부모 클래스의 생성자가 먼저 호출되고 이후에 자식 클래스의 생성자가 호출되므로 super 키워드를 사용하기 위해서는 반드시 첫번째 줄에 작성 해야한다. (왜냐하면 자식 클래스의 인스턴스 변수들이 초기화 되기 전에 부모클래스의 생성자가 호출 되어야하기 때문이다.) super() 는 부모의 생성자를 호출할 수 있다. 이 키워드를 이용하면 코드의 가독성을 높이고 중복 코드를 줄일 수 있다.다음 클래스들이 있습니다. testMain 클래스를 디버깅하면 testB 와 testBB의 주솟값은 서로 다를까요? 다르다면 왜 다르고 같다면 왜 같은걸까요?
//test 패키지 안에 A 클래스
package test;
public class A {
void methodA() {
System.out.println("A");
}
}
//동일 패키지에 B 클래스
package test;
public class B extends A{
@Override
void methodA() {
System.out.println("B는 A 상속받았다");
}
void methodB() {
System.out.println("이거는 B만의 메소드이다");
}
}
//동일 패키지에 C 클래스
package test;
public class C extends A {
@Override
void methodA() {
System.out.println("C도 A 상속받았다");
}
void methodC() {
System.out.println("이거는 B만의 메소드이다");
}
}
//main
package test;
public class testMain {
public static void main(String[] args) {
A testB = new B();
A testC = new C();
testB.methodA(); //B는 A 상속받았다
testC.methodA(); //C도 A 상속받았다
B testBB = (B)testB;
System.out.println(testB);
System.out.println(testBB); //testB와 testBB는 같은 주소값을 출력한다.
}
}
김은서
메서드를 하위클래스부터 찾아가기 때문에, (2번 문제에서도 다뤘듯이) 다형성을 통해 인스턴스를 생성하였을 때 부모 클래스의 메서드를 자식 클래스에서 오버라이딩 한 경우 오버라이딩 된 메서드를 호출되는 형태가 나온다고 생각하면 될 것 같다.
즉, 하위클래스에서 오버라이딩이 되어 있으면 부모가 아닌 자식클래스에서 호출 된다.
B testBB = (B) testB;
testBB는 B타입이고, B타입은 A를 상속 받고 있고, testB는 A타입이다. 실제로 testBB는 초록색 박스 전체를 볼 수 있다. testBB라는 값을 testB로 초기화했으나, testB는 A부분밖에 보지 못하므로 B타입으로 형변환을 시켜주었다.
따라서 testBB는 A와 B 모두를 호출 할 수 있다.
김은서(질문)
그렇다면 더 넓은 범위의 메서드를 가지게 된 testBB에서의 print A 와, testB에서의 print A는 같은가?
신동현 (답변)
같다. 메서드를 하위 클래스부터 찾아가는 형식은 변함 없으니 오버라이딩 된 메서드를 호출한다.
A testB = new B();
김은서
testB는 클래스 A에 있는 메서드와 클래스 B에서 오버라이딩 한 메서드만을 사용할 수 있다.
하지만 B 클래스의 데이터 타입으로 testB를 감싸며 클래스 B에서 오버라이딩 하지 않은, 클래스 B에서만 있는 메서드 또한 사용할 수 있게 되었기 때문에 더 넓은 의미의 다형성을 사용할 수 있게 된 것이다.
참고 자료