scala - 对象扩展 Trait,类扩展 Trait,两者都必须实现方法

标签 scala object collections singleton traits

我有以下设置:

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/

相关文章:

c++ - 如何在同一个函数中创建多个对象而不互相覆盖?

java - 使用Java在 map 中自动创建缺失值的成语

java - Java 程序内存中的大型静态映射

scala - 如何使用 Mockito 模拟返回值类实例的函数?

javascript - 对象到数组返回未定义

python - Python 中哪些对象可以动态添加属性?

java - java中的数字和字母二叉树

scala - 在 Scala 中 - 将案例类列表转换为元组列表

scala - 如何修复 Spark 严重误解 csv 的问题?

scala - 如何在 Scala 中编写高效的 groupBy-size 过滤器,可以近似