我有以下设置:
trait A
{
def doSomething(): Unit;
}
object B extends A
{
override def doSomething(): Unit =
{
// Implementation
}
}
class B(creator: String) extends A
{
override def doSomething(): Unit =
{
B.doSomething() // Now this is just completely unnecessary, but the compiler of course insists upon implementing the method
}
}
现在你可能想知道为什么我要这样做,为什么我也让类扩展这个特征。
问题是,程序中的某个地方有一个 A 的集合。 所以某处:
private val aList: ListBuffer[A] = new ListBuffer[A]
在那里,我还必须输入 Bs(以及其他衍生物,即 C 和 D)
所以我不能让B级不扩展它。
由于所有实例的实现都是相同的,我想要使用对象。
但是我真的需要这个对象也是有原因的。因为有一个类:
abstract class Worker
{
def getAType(): A
def do(): Unit =
{
getAType().doSomething()
}
}
class WorkerA
{
def getAType(): A =
{
return B
}
}
这里返回 B 的单例/对象。这是在 Worker 中实现 do() 所必需的。
总结:
由于 do()(Worker-Class)中的通用实现,并且 doSomething() 永远不会改变,因此需要对象 B。
需要类 B,因为在 BaseType A 的集合中,存在不同作者的不同 B 实例。
由于上述原因,对象和类都必须实现该特征,所以我在这里陷入了困境。我找不到看起来更整洁的令人满意的解决方案。所以,我的问题是(事实证明,作为非母语人士,我应该进一步澄清这一点)
有没有办法让一个类扩展一个特征(或类),并说任何抽象方法实现都应该在对象而不是类中查找,这样我就必须只实现“doSomething()”(来自特征)一次(在对象中)?正如我所说,该特质在这里完成了两项不同的任务。 一种是 BaseType,以便集合可以获得该类的实例。另一个是确保每个对象中都存在 doSomething() 方法的契约。
因此,对象 B 需要扩展特征,因为特征就像 Java 接口(interface),并且每个(!)对象 B(或 C 或 D)需要有那个方法。 (所以我看到的唯一选项 -> 定义一个接口(interface)/特征并确保该方法存在)
编辑:以防万一有人想知道。我是如何真正解决这个问题的:我实现了两个特征。
现在,对于一个类(我需要它的地方),我扩展了两个类,而对于另一个类,我只扩展了一个类。所以我实际上从来不需要实现任何不是绝对必要的方法:)
最佳答案
正如我在评论部分所写的,我真的不清楚你在问什么。
但是,查看您的代码示例,在我看来,trait A
并不是真正需要的。
您可以使用 Scala SDK 附带的类型:
object B extends (()=>Unit) {
def apply() { /* implementation */ }
}
或者,作为变体:
object B {
val aType:()=>Unit = {() => /* implementation */ }
}
在第一种情况下,您可以使用 B
访问单例实例,在第二种情况下,可以使用 B.aType
访问单例实例。
在第二种情况下,不需要显式声明 apply
方法。
选择你喜欢的。 基本信息是:如果您只定义一个简单的方法,则不需要特征。 这就是 Scala 函数的用途。
列表类型可能如下所示:
private val aList:ListBuffer[()=>Unit] = ???
(顺便说一句:为什么不将其声明为 Seq[()=>Unit]
?对于调用者来说,它是一个 ListBuffer
而不是一些重要的东西吗?其他类型的序列?)
您的工作人员可能如下所示:
abstract class Worker {
def aType:()=>Unit // no need for the `get` prefix here, or the empty parameter list
def do() {aType()}
}
请注意,现在 Worker
类型已成为提供调用函数的方法的类。
因此,实际上没有必要有一个 Worker 类。
您可以直接获取函数 (aType
) 并调用它,就这样。
如果您总是想调用对象 B
中的实现,那么 - 就这样做吧。
无需将调用包装在其他类型的实例中。
您的示例类 B
只是将调用转发给 B
对象,这实际上是不必要的。
甚至不需要创建 B
的实例。
它确实有私有(private)成员变量creator
,但由于它从未被使用过,所以永远不会以任何方式访问它。
因此,我建议完全删除B 类
。
您所需要的只是 ()=>Unit
类型,这正是您所需要的:一个不带参数且不返回任何内容的函数。
如果您厌倦了一直编写 ()=>Unit
,您可以定义一个类型别名,例如在包对象内。
这是我的建议:
type SideEffect = ()=>Unit
然后您可以使用 SideEffect
作为 ()=>Unit
的别名。
我能想到的就这么多了。 在我看来,这可能不是您想要的。 但也许这会对你有所帮助。 如果您想得到更具体的答案,最好能澄清问题。
关于scala - 对象扩展 Trait,类扩展 Trait,两者都必须实现方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31441019/