왜 클래스가 동일한 서명의 방법으로 특성을 확장 할 수 없습니까?

StackOverflow https://stackoverflow.com/questions/1836060

  •  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

유형 계층으로 호출 결과 hiS는 다음과 같습니다 ( {} 특성을 인스턴스화하기 위해) :

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()
}

특성을 사용하는 가장 영리한 방법은 아니지만 프로젝트 코드의 변경이 필요하지 않으며 테스트에 약간 더 많은 코드가 있다는 것을 의미합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top