클래스 확장

클래스 확장 (Extend a class)

상위 클래스(superclass)로부터 하위 클래스(subclass)를 만드는 방법을 살펴볼게요. 객체지향 언어에서 상속은 익숙한 개념이지만, Dart에서 주의할 점이 몇 가지 있어요.

출처: Dart 공식 문서

본문

extends로 하위 클래스를 만들고, super로 상위 클래스를 참조해요.

class Television {
  void turnOn() {
    _illuminateDisplay();
    _activateIrSensor();
  }
  // ···
}

class SmartTelevision extends Television {
  void turnOn() {
    super.turnOn();
    _bootNetworkInterface();
    _initializeMemory();
    _upgradeApps();
  }
  // ···
}

extends의 또 다른 용법에 대한 설명은 Generics 페이지의 파라미터화 타입(parameterized types) 논의를 참고하세요.

멤버 오버라이딩 (Overriding members)

하위 클래스는 인스턴스 메서드(연산자 포함), getter, setter를 오버라이드할 수 있어요. 자신이 의도적으로 멤버를 오버라이드하고 있음을 나타내려면 @override annotation을 쓸 수 있어요.

class Television {
  // ···
  set contrast(int value) {
    // ···
  }
}

class SmartTelevision extends Television {
  @override
  set contrast(num value) {
    // ···
  }
  // ···
}

오버라이드하는 메서드 선언은 여러 면에서 오버라이드 대상 메서드와 일치해야 해요.

  • 반환 타입은 오버라이드된 메서드의 반환 타입과 같거나(또는 그 하위 타입이어야) 해요.
  • 파라미터 타입은 오버라이드된 메서드의 파라미터 타입과 같거나(또는 그 상위 타입이어야) 해요. 앞선 예시에서 SmartTelevision의 contrast setter는 파라미터 타입을 int에서 상위 타입인 num으로 바꿨어요.
  • 오버라이드된 메서드가 n개의 위치 파라미터를 받는다면, 오버라이드하는 메서드도 n개의 위치 파라미터를 받아야 해요.
  • 제네릭 메서드는 비제네릭 메서드를 오버라이드할 수 없고, 비제네릭 메서드도 제네릭 메서드를 오버라이드할 수 없어요.

때로는 메서드 파라미터나 인스턴스 변수의 타입을 더 좁히고 싶을 수 있어요. 이는 일반 규칙을 위반하고, 다운캐스트와 비슷하게 런타임에서 타입 오류를 일으킬 수 있어요. 그래도 코드가 타입 오류가 발생하지 않음을 보장할 수 있다면 타입을 좁히는 게 가능해요. 이 경우 파라미터 선언에서 covariant 키워드를 사용하면 됩니다. 자세한 내용은 Dart 언어 명세를 참고하세요.

경고

==를 오버라이드한다면 ObjecthashCode getter도 함께 오버라이드해야 해요. ==hashCode를 오버라이드하는 예시는 Implementing map keys를 확인해 보세요.

noSuchMethod()

코드가 존재하지 않는 메서드나 인스턴스 변수를 사용하려 할 때 이를 감지하거나 반응하려면 noSuchMethod()를 오버라이드하면 돼요.

class A {
  // Unless you override noSuchMethod, using a
  // non-existent member results in a NoSuchMethodError.
  @override
  void noSuchMethod(Invocation invocation) {
    print(
      'You tried to use a non-existent member: '
      '${invocation.memberName}',
    );
  }
}

구현되지 않은 메서드를 호출할 수 없는 경우는, 다음 중 하나가 참일 때예요.

  • 수신자의 정적 타입이 dynamic인 경우.
  • 수신자의 정적 타입이 구현되지 않은 메서드를 정의하고(추상이어도 OK), 수신자의 동적 타입이 Object 클래스의 것과 다른 noSuchMethod() 구현을 가진 경우.

자세한 내용은 비공식 noSuchMethod 포워딩 명세를 참고하세요.

더 알아보기