경주장

6주차 과제: 상속 #6 (~02.29) - 메소드 오버라이딩 본문

JAVA/whiteship_live-study

6주차 과제: 상속 #6 (~02.29) - 메소드 오버라이딩

달리는치타 2022. 2. 22. 16:38

✔️ 학습할 것 (필수)

  • 자바 상속의 특징
  • 메소드 오버라이딩
  • final 키워드
  • super 키워드
  • 다이나믹 메소드 디스패치 (Dynamic Method Dispatch)
  • 추상 클래스
  • Object 클래스

 

메소드 오버라이딩의 경우 Instance 메소드와 static 메소드두가지 종류가 있습니다.

 

Instance 메소드

An instance method in subclass with the same signature and return type as an instance method in the superclass overrides the superclass's method

Subclass의 메소드 오버라이딩은 superclass의 메소드와 "충분히 비슷한" 메소드를 쉽게 작성 할 수 있게해줍니다. overriding method는 오버라이드된 메소드와 같은 리턴타입, 메소드이름, 파라미터 종류와 숫자(리턴타입 + 메소드 시그니처)를 가집니다. 또한 리턴타입의 경우 오버라이드된 메서드의 리턴타입의 하위 타입(subtype)을 반환 할 수도 있습니다. 이러한 subtype을 covariant return type이라고 부릅니다.

 

@Override 어노테이션은 컴파일러에게 명시적으로 superclass의 메소드를 override하고자 함을 알려주기 위해 사용됩니다. 작성하지 않아도 문제가 되지 않지만 코드의 가독성, 명확성을위해 꼭 작성하여야 합니다.

 

static 메소드

subclass가 superclass의 static 메소드와 같은 signature를 가진 static 메소드를 정의한다면 subclass의 메소드는 superclass의 메소드를 hide 하였다고 표현합니다. 

static 메소드가 부모의 메소드를 hide 하는것과 instance 메소드가 부모의 메소드를 override하는것에는 중요한 의미적인 차이가 있습니다.

 

  • The version of the overridden instance method that gets invoked is the one in the subclass
    • instance method의 경우 실제 invoke되는 메소드는 subclass의 method입니다.
  • The version of the hidden static method that gets invoked depends on wheter it is invoked from the superclass or the subclass
    • static method의 경우 실행하는 Class의 종류에 따라 실제 호출되는 method의 종류가 결정됩니다.

Interface의 default method와 abstract 메소드에의해 자바 클래스는 같은 signature를 가진 메소드를 여러 출처 (클래스(1...) + 인터페이스(n))로 부터 상속할 수 있습니다.

 

이경우 자바 컴파일러는 두가지 규칙에 따라 상속받을 메소드를 결정합니다.

 

규칙 1 Instance methods are preferred over interface default methods.

 

public class Horse {
    public String identifyMyself() {
        return "I am a horse.";
    }
}
public interface Flyer {
    default public String identifyMyself() {
        return "I am able to fly.";
    }
}
public interface Mythical {
    default public String identifyMyself() {
        return "I am a mythical creature.";
    }
}
public class Pegasus extends Horse implements Flyer, Mythical {
    public static void main(String... args) {
        Pegasus myApp = new Pegasus();
        System.out.println(myApp.identifyMyself());
    }
}

=> The method Pegasus.identifyMyself returns the string I am a horse.

 

즉, 상속이 하나 포함된경우 method 시그니처의 conflict이 발생하였을때 상속이 interface의 default 메소드보다 우위를 가집니다.


규칙 2 Methods that are already overridden by other candidates are ignored. This circumstance can arise when supertypes share a common ancestor.

이미 다른 후보로부터 상속을 받았다면 그 후보는 무시합니다.

즉 아래와 같은 상황에서 FireBrether에대한 구현은 무시됩니다.

 

public interface Animal {
    default public String identifyMyself() {
        return "I am an animal.";
    }
}
public interface EggLayer extends Animal {
    default public String identifyMyself() {
        return "I am able to lay eggs.";
    }
}
public interface FireBreather extends Animal { }
public class Dragon implements EggLayer, FireBreather {
    public static void main (String... args) {
        Dragon myApp = new Dragon();
        System.out.println(myApp.identifyMyself());
    }
}

요 코드에서 method Dragon.identifyMyself 는 "I am able to lay eggs."를 리턴합니다.

 

드래곤의 입장에서 자신을 identify하기위해 매소드의 구현부를 찾으러 모험을 떠나면 위와같은 화살표를 따라 탐색이 진행됩니다. FireBreather가 Animal을 상속하는 것을 확인하였지만 Animal은 이미 EggLayer가 상속하였기 때문에 탐색하지 않습니다. 따라서 EggLayer의 default 메서드가 실행됩니다.

 

이때 FireBreather도 identifyMyself를 override하게 되면 compile에러가 발생합니다. 인텔리제이는 Dragon에 identifyMyself메소드를 구현할 것을 제안하고 억지로 실행하게 되면 아래와 같은 에러가 발생합니다.

java: types EggLayer and FireBreather are incompatible;

 


추가로 접근제어자의 경우 Override할때 subclass가 더 넓은 범위의 접근 제어자를 가지도록 할 수 있습니다.

Modifiers

The access specifier for an overriding method can allow more, but not less, access than the overridden method. For example, a protected instance method in the superclass can be made public, but not private, in the subclass.

 

 

또한 instance method를 static method로 override하거나 static method를 instance method로 override하는 것은 금지되어 있습니다.

  Superclass Instance Method Superclass Static Method
Subclass Instance Method Overrides Generates a compile-time error
Subclass Static Method Generates a compile-time error Hides

 

또또 추가로 subclass에서는 superclass로부터 상속받은 메서드를 overload할 수 있는데 이것은 overriding이나 hide가 아니라 그냥 subclass에 유니크한 새로운 메소드를 생성한 것입니다.