Scala特质和case对象的正确使用方法

3

如果你正在尝试掌握Scala类和特质,这里有一个简单的例子。我想定义一个类,它指定了多种操作,可以用许多方式实现。我可能会从以下内容开始:

sealed trait Operations{
  def add
  def multiply
}

例如,我可能会使用一个带有`add`和`multiply`方法的对象实例化这个类,这些方法非常合理。
case object CorrectOperations extends Operations{
    def add(a:Double,b:Double)= a+b
    def multiply(a:Double,b:Double)= a*b
}

此外,还有其他定义这些操作的方法,例如这种明显错误的方法:
case object SillyOperations extends Operations{
    def add(a:Double,b:Double)= a + b - 10
    def multiply(a:Double,b:Double)= a/b
}

我希望将这样一个实例传递到一个函数中,该函数将以特定方式执行操作。
 def doOperations(a:Double,b:Double, op:operations) = {
   op.multiply(a,b) - op.add(a,b)
 }

我希望 doOperations 可以接受任何类型为operations的对象,这样我就可以使用其中的addmultiply方法。请问我需要如何修改doOperations方法?我的理解是否正确?谢谢。
1个回答

5
我还没有运行你的代码,但我猜想你遇到了编译错误。
如果你不定义 Operations 特质中方法的签名,那么默认情况下它将被解释为 () => Unit
这意味着继承对象中的方法并不真正覆盖特质中的方法,而是定义了重载。在这里可以了解更多信息。你可以通过在对象方法的方法定义前面写上 override 来验证这一点。这将强制编译器明确警告你这些方法没有覆盖任何祖先特质中的内容,并作为防止类似错误的“安全网”。
要修复这个错误,请像以下这样详细说明特质的签名:
sealed trait Operations{
  def add(a:Double,b:Double):Double
  def multiply(a:Double,b:Double):Double
}

事实上,在继承对象的方法中,输出参数类型甚至不是必需的(但请注意添加的 override 属性):
case object CorrectOperations extends Operations{
    override def add(a:Double,b:Double) = a+b
    override def multiply(a:Double,b:Double) = a*b
}

1
谢谢!所以你的第二个代码块对我来说不起作用,override def add = a+b,似乎我仍然需要签名... - keegan
1
@keegan 抱歉,你说得对,它需要输入参数...但不需要输出。请查看已编辑的版本。 - Daniel Dinnyes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接