왜 클래스가 동일한 서명의 방법으로 특성을 확장 할 수 없습니까?
-
11-09-2019 - |
문제
아래에서 오류가 발생하는 이유는 무엇입니까? 해결 방법은?
A와 B가 (인터페이스, 클래스) 쌍으로 컴파일하기 때문에 C 컴파일 C를 컴파일 할 때 구현할 수있는 올바른 정적 메소드 호출을 선택하는 문제라고 가정했습니다. 우선 순위는 주문에 따라 될 것으로 기대합니다.
scala> trait A { def hi = println("A") }
defined trait A
scala> trait B { def hi = println("B") }
defined trait B
scala> class C extends B with A
<console>:6: error: error overriding method hi in trait B of type => Unit;
method hi in trait A of type => Unit needs `override' modifier
class C extends B with A
scala> trait A { override def hi = println("A") }
<console>:4: error: method hi overrides nothing
trait A {override def hi = println("A")}
루비에서는 이것이 잘 작동합니다.
>> module B; def hi; puts 'B'; end; end
=> nil
>> module A; def hi; puts 'A'; end; end
=> nil
>> class C; include A; include B; end
=> C
>> c = C.new
=> #<C:0xb7c51068>
>> c.hi
B
=> nil
해결책
이것은 2.8과 2.11에서 저에게 효과적이며, 당신이 특성에 대해 무관심 할 수 있습니다. A
또는 B
:
trait A { def hi = println("A") }
trait B { def hi = println("B") }
class C extends A with B {
override def hi = super[B].hi
def howdy = super[A].hi // if you still want A#hi available
}
object App extends Application {
(new C).hi // prints "B"
}
다른 팁
공통 기본 특성을 사용할 수 있습니다 Base
, 다음과 같이 :
trait Base {def hi: Unit}
trait A extends Base {override def hi = println("A")}
trait B extends Base {override def hi = println("B")}
class C extends A with B
유형 계층으로 호출 결과 hi
S는 다음과 같습니다 ( {}
특성을 인스턴스화하기 위해) :
scala> (new A {}).hi
A
scala> (new B {}).hi
B
scala> (new C).hi
B
특성은 클래스에 혼합하는 방법을 추가합니다. 두 가지 특성이 동일한 방법을 추가하면 클래스는 두 가지 동일한 방법으로 끝날 수 없습니다.
그러나이 방법이 특성에서 비공개 인 경우 문제가 발생하지 않습니다. 그리고 메소드가 서로 쌓일 수있는 방법을 원한다면 기본 특성을 정의한 다음 abstract override
상속 특성에. 그러나 메소드를 정의하려면 클래스가 필요합니다. 다음은 다음과 같습니다.
scala> trait Hi { def hi: Unit }
defined trait Hi
scala> trait A extends Hi { abstract override def hi = { println("A"); super.hi } }
defined trait A
scala> trait B extends Hi { abstract override def hi = { println("B"); super.hi } }
defined trait B
scala> class NoHi extends Hi { def hi = () }
defined class NoHi
scala> class C extends NoHi with B with A
defined class C
scala> new C().hi
A
B
그러나 각 특성에서 두 가지 별도의 방법을 원한다면 구성하다 대신에 상속.
이것이 다이아몬드 문제. 어떤 방법 hi
상속, A에서 나온 것 또는 B의 하나를 상속해야합니까? 일반적인 기본 특성을 사용하여 Don이 제안한 대로이 문제를 해결할 수 있습니다.
나는 같은 문제가 있었고 동일한 방법으로 4,5 또는 6 개의 특성을 가질 수 있기 때문에 중개 특성을 만들고 싶지 않았다. 또한 테스트 목적으로 만 해당 특성을 함께 사용해야했으며 항상 테스트를보다 쉽게하기 위해 프로젝트의 구조를 수정하기 위해 가능한 한 많은 것을 피하려고 노력합니다. 그래서 나는 단순히 다른 객체에서 이러한 특성을 구현했습니다.
class somethingToTest {
object AImpl extends ATrait
object BImpl extends BTrait
val a = AImpl.methodDuplicated()
val b = BImpl.methodDuplicated()
}
특성을 사용하는 가장 영리한 방법은 아니지만 프로젝트 코드의 변경이 필요하지 않으며 테스트에 약간 더 많은 코드가 있다는 것을 의미합니다.