我可以安全地继承具有相同方法的特征和基类吗?
赞:
trait MyTrait {
def getValue:String
}
class SomeClass {
def getValue:String = [concrete implementation]
}
然后:
class MyClass extends SomeClass with MyTrait
这样做的原因是我想在另一个(抽象)类中使用它,该类仅通过MyTrait
特征来定义所需的API,而我不能让SomeClass
继承此特征直接(因为它来自另一个不相关的库)。
abstract class AbstractOtherClass {
val mainObject:MyTrait
}
然后是该类的具体实现:
class OtherClass extends AbstractOtherClass {
val mainObject:MyTrait = new MyClass
def something = {
println(mainObject.getValue) // shall call SomeClass.getValue
}
}
解决方案
在SergGr的建议之后,我最终得到了这样的解决方案:
abstract class AbstractOtherClass {
def getValue:String
}
class OtherClass extends AbstractOtherClass {
val mainObject:SomeClass = ...
def getValue:String = mainObject.getValue
}
答案 0 :(得分:1)
这里似乎有两个不同的问题
只要您的trait
仅声明了方法但没有实现,则它是设计使然的。这是不寻常但预期的使用模式之一。如果多个trait
或trait
和class
具有相同方法的实现,则linearization仍将有一个明确指定的逻辑,该逻辑指定如何解决冲突,但是我会说,在大多数情况下,依靠它是一个糟糕的设计。
您尝试做的事情对我来说像adapter pattern,我想说从设计的角度来看,最好使用对象组合而不是继承来实现它。
trait MyTrait {
def getValue:String
}
class SomeClassWrapper(delegate: SomeClass) extends MyTrait {
override def getValue:String = delegate.getValue
}
通过这种方式,您不会将API绑定到库的实现。例如,如果在上下文中更有意义,则可以将方法重命名为getAbcValue
值。或者,如果您在某个时候找到另一个库,它的性能更好,但该方法的名称不同(例如calculateValue
),则只需创建另一个包装器类,而不必更改所有getValue
个呼叫到calculateValue
个呼叫。