강의 내용
[1] 상속 체이닝과 super
[2] 메서드의 재정의(Override)
[1] 상속 체이닝과 super
상속 관계에서 객체를 생성할 때 등장하는 개념
상속 체이닝
맨 위 부모 클래스부터 객체가 생성되어 자식까지 연결되는 구조(나보다 부모가 먼저)
상속의 연결 고리가 체인처럼 연결된 형태를 갖는다.
super
상위 클래스의 생성자를 호출하는 메서드
생성자 메서드 안에서 반드시 첫 번째 문장에 적어줘야 한다.
자식 클래스가 만들어지기 이전에 부모 클래스가 먼저 만들어져야 한다.
부모 클래스가 만들어지지 않은 상태에서 자식 클래스를 초기화할 수 없기 때문이다.
자식 클래스의 수행문은 부모 클래스가 만들어진 다음 자식 클래스가 만들어질 때 수행된다.
부모 클래스의 기본 생성자를 호출하는 super()는 생략 가능하다.
예) A → B → C
A 객체가 만들어지기 전에 부모의 객체가 먼저 만들어져야 한다.
A 객체를 사용하기 위해 객체를 만들면 A 객체의 생성자에서 부모의 생성자가 호출된다.
[메모리 생성 순서] C → B → A
□ C
□ B
□ A
예) Dog → Animal → Object
[메모리 생성 순서] Object → Animal → Dog
□ Object
□ Animal
□ Dog
public class Object { } public class Animal extends Object { public Animal() { super(); // new Object() } } public class Dog extends Animal { public Dog() { super(); // new Animal() } }
Dog d = new Dog(); // 접근 가능한 범위 : Animal, Dog Animal a = new Dog(); // 접근 가능한 범위 : Animal
Q. Dog와 Cat클래스를 설계하고 동작시켜 보시오.
public class Animal extends Object { // 동물 : 개와 고양이를 포괄 public Animal() { // 기본 생성자 super(); // new Object(); } public void eat() { System.out.println("동물처럼 먹다."); } }
public class Dog extends Animal { public Dog() { // 기본 생성자 super(); // new Animal(); } }
public class Cat extends Animal { public Cat() { // 기본 생성자 super(); // new Animal(); } public void night() { System.out.println("밤에 눈에서 빛이 난다."); } }
public class DogCatUpcastingTest { public static void main(String[] args) { // Upcasting(업캐스팅) : 부모가 자식을 가리킴 Animal an = new Dog(); an.eat(); // 동물처럼 먹다 -> 개처럼 먹다 an = new Cat(); an.eat(); // 동물처럼 먹다 -> 고양이처럼 먹다 } }
자식 클래스의 동작 방식을 모를 때는 부모 클래스를 이용하여 자식 클래스를 동작시켜야 한다.
Animal에서 Dog의 기억 공간에 접근할 수 있어야 Animal로 Dog를 구동할 수 있다.
부모가 자식을 구동하려면 부모가 갖는 동작을 자식이 물려받아 자기 용도에 맞게 재정의 해야 한다.(override)
[eat(){}] Animal
[eat(){}] Dog
[2] 메서드의 재정의(Override)
동적 바인딩
어떤 메서드가 부모의 메서드인지 자식의 메서드인지는 실행해야 알 수 있다(컴파일 시점에서는 알 수 없음)
[컴파일러]
(1) 실행
(2) 부모 클래스의 메서드를 찾음
(3) 해당 메서드를 자식 클래스가 재정의 했는지 찾음
(4) 자식 클래스가 재정의 했다면 제어권이 넘어가게 되면서 자식 클래스의 메서드를 실행
메서드의 재정의(Override)
부모의 기능을 자식에게 상속하면 자식은 부모의 기능을 마음대로 사용할 수 있다.
자식이 부모의 기능을 다시 정의하여 자신에게 맞는 행동 방식으로 사용 할 수 있다.(재정의, override)
재정의할 수 없다면 부모의 기능을 그대로 사용해야 한다.
*재정의 : 부모로 하여금 자식에게 접근 가능한 연결 고리
실습
Q. Dog와 Cat클래스를 설계하고 동작시켜 보시오.
자식의 동작 방식을 모르지만 부모를 통해 자식을 구동시키는 방법
public class Animal { // 동물 : 개와 고양이를 포괄 public Animal() { // 기본 생성자 super(); // new Object(); } public void eat() { System.out.println("동물처럼 먹다."); } }
public class Dog extends Animal { public Dog() { // 기본 생성자 super(); // new Animal(); } // 재정의(Override) public void eat() { System.out.println("개처럼 먹다"); } }
public class Cat extends Animal { public Cat() { // 기본 생성자 super(); // new Animal(); } public void night() { System.out.println("밤에 눈에서 빛이 난다."); } // 재정의(Override) public void eat() { System.out.println("고양이처럼 먹다"); } }
public class OverrideTest { public static void main(String[] args) { // Upcasting(업캐스팅) : Dog.java(X), Animal <---> Dog.class(O) Animal an = new Dog(); an.eat(); // Animal---(동적 바인딩)--->Dog an = new Cat(); an.eat(); // Animal---(동적 바인딩)--->Cat } }
Animal an = new Dog(); an.eat(); // Animal---(동적 바인딩)--->Dog // (1) 컴파일 시점 : Animal eat(){} // (2) 실행 시점(재정의 O) : Dog eat(){} // (3) 실행 시점(재정의 X) : Animal eat(){} an = new Cat(); an.eat(); // Animal---(동적 바인딩)--->Cat // (1) 컴파일 시점 : Animal eat(){} // (2) 실행 시점(재정의 O) : Cat eat(){} // (3) 실행 시점(재정의 X) : Animal eat(){}
본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.
https://bit.ly/48sS29N