mixin_application_concrete_super_invoked_member_type 진단: super로 호출한 멤버의 타입이 실제 구현과 달라요

mixin_application_concrete_super_invoked_member_type 진단: super로 호출한 멤버의 타입이 실제 구현과 달라요

분석기가 내보내는 진단에는 이름이 있어요. mixin_application_concrete_super_invoked_member_typesuper를 통해 호출하는 멤버의 시그니처가, mixin이 선언한 on 타입에 정의된 시그니처와 다른 클래스에서 mixin이 사용될 때 Dart 분석기가 알려주는 컴파일 타임 진단이에요. 이 경우 mixin 안의 호출이 실제로 실행될 메서드와는 맞지 않는 방식으로 호출될 수 있기 때문에 오류가 되는 거예요.

출처: mixin_application_concrete_super_invoked_member_type

본문

설명

분석기는 super를 사용해 메서드를 호출하는 mixin이, 그 메서드의 실제 구현(concrete implementation)이 mixin의 on 타입에 정의된 시그니처와 다른 시그니처를 가진 클래스에 적용될 때 이 진단을 만들어요. 오류인 이유는 mixin 안의 호출이 실제로 실행될 메서드와 호환되지 않는 방식으로 그 메서드를 호출할 수 있기 때문이에요.

예시

다음 코드는 클래스 C가 mixin M을 사용하고, mixin Msuperfoo를 호출하는데, I(mixin의 on 타입)에 선언된 추상 버전의 fooA에 선언된 실제 버전의 foo와 시그니처가 같지 않아서 이 진단이 나와요.

class I {
 void foo([int? p]) {}
}

class A {
 void foo(int p) {}
}

abstract class B extends A implements I {
 @override
 void foo([int? p]);
}

mixin M on I {
 void bar() {
  super.foo(42);
 }
}

abstract class C extends B with M {}

흔한 해결 방법

클래스가 mixin을 쓸 필요가 없다면, with 절에서 mixin을 빼 버려요.

class I {
 void foo([int? p]) {}
}

class A {
 void foo(int? p) {}
}

abstract class B extends A implements I {
 @override
 void foo([int? p]);
}

mixin M on I {
 void bar() {
  super.foo(42);
 }
}

abstract class C extends B {}

클래스가 mixin을 꼭 써야 한다면, mixin이 기대하는 시그니처에 맞는 실제 구현을 가진 메서드가 있도록 만들어 줘요.

class I {
 void foo([int? p]) {}
}

class A {
 void foo(int? p) {}
}

abstract class B extends A implements I {
 @override
 void foo([int? p]) {
  super.foo(p);
 }
}

mixin M on I {
 void bar() {
  super.foo(42);
 }
}

abstract class C extends B with M {}

더 알아보기