E137: Illegal Super Accessor — 잘못된 슈퍼 접근자
E137: Illegal Super Accessor — 잘못된 슈퍼 접근자
슈퍼 접근자(super-accessor)를 구현할 때 부모 트레이트들 사이에서 충돌이 생겨 클래스를 정의할 수 없을 때 발생하는 에러예요.
본문
트레이트가 부모를 명시적으로 지정하지 않고(super[Parent].method처럼) super.method를 호출하면, Scala는 이 클래스를 상속하는 클래스 안에 선형화(linearization) 순서에 기반한 슈퍼 접근자를 생성해요. 그런데 해석된 슈퍼 호출의 반환 타입이 트레이트가 기대하는 타입과 호환되지 않으면 이 에러가 발생해요.
이 문제는 보통 다음 상황에서 일어나요.
예시
class X
class Y extends X
trait A[+T]:
def foo: T = null.asInstanceOf[T]
trait B extends A[X]:
override def foo: X = new X
trait C extends A[Y]:
override def foo: Y = new Y
def superFoo: Y = super.foo
class Fail extends B with C
에러
-- [E137] Declaration Error: example.scala:14:6 --------------------------------
14 |class Fail extends B with C
| ^
|class Fail cannot be defined due to a conflict between its parents when
|implementing a super-accessor for foo in trait C:
|
|1. One of its parent (C) contains a call super.foo in its body,
| and when a super-call in a trait is written without an explicit parent
| listed in brackets, it is implemented by a generated super-accessor in
| the class that extends this trait based on the linearization order of
| the class.
|2. Because B comes before C in the linearization
| order of Fail, and because B overrides foo,
| the super-accessor in Fail is implemented as a call to
| super[B].foo.
|3. However,
| X (the type of super[B].foo in Fail)
| is not a subtype of
| Y (the type of foo in trait C).
| Hence, the super-accessor that needs to be generated in Fail
| is illegal.
|
|Here are two possible ways to resolve this:
|
|1. Change the linearization order of Fail such that
| C comes before B.
|2. Alternatively, replace super.foo in the body of trait C by a
| super-call to a specific parent, e.g. super[A].foo
해결 방법
트레이트 안에서 명시적인 슈퍼 호출을 사용하면 돼요.
// Use explicit super-call in the trait
class X
class Y extends X
trait A[+T]:
def foo: T = null.asInstanceOf[T]
trait B extends A[X]:
override def foo: X = new X
trait C extends A[Y]:
override def foo: Y = new Y
def superFoo: Y = super[A].foo
class Fixed extends B with C