Scala case类和继承:如何提供不同的行为
情况:Scala case类和继承:如何提供不同的行为,scala,case-class,traits,self-type,Scala,Case Class,Traits,Self Type,情况: trait Operation { def something: Double } trait OperationPlus { this: A => override def something: Double = x + y } trait OperationMinus { this: A => override def something: Double = x - y } case class A(x: Double, y: Double) { this:
trait Operation {
def something: Double
}
trait OperationPlus { this: A =>
override def something: Double = x + y
}
trait OperationMinus { this: A =>
override def something: Double = x - y
}
case class A(x: Double, y: Double) { this: Operation =>
}
val a = new A(1.0, 2.0) with OperationPlus
println(a.something)
错误:
class A cannot be instantiated because it does not conform to its self-type A with Operation
而且,我不能实例化一个
我尝试了多种不同的方法,但都没有提供我想要的。我不想使用case类继承,也不想放弃case类,理想情况下,trait/self-types/其他东西应该可以做到这一点。有什么想法吗
更新
首选解决方案
trait Operation { this: A =>
def something: Double
}
trait OperationPlus extends Operation { this: A =>
override def something: Double = x + y
}
trait OperationMinus extends Operation { this: A =>
override def something: Double = x - y
}
abstract case class A(val x: Double, val y: Double) extends Operation
val a = new A(1.0, 2.0) with OperationPlus
println(a.something)
val b = new A(1.0, 2.0) with OperationMinus
println(b.something)
可能的解决办法1:
trait Operation {
def x:Double
def y:Double
def something: Double
}
trait OperationPlus extends Operation {
override def something: Double = x + y
}
trait OperationMinus extends Operation {
override def something: Double = x - y
}
abstract case class A(val x: Double, val y: Double) extends Operation
通过使用常规类,简单的特征继承和实际值中的自我类型可以定义它并动态提供行为
不幸的是,我必须重新定义trait中的字段。我想这是一个公平的妥协。我想知道是否有人知道另一种方法
谢谢不确定您的用例,但是如果您想让它工作,您需要像这样定义class
A
:
abstract case class A(x: Double, y: Double) extends Operation
但我不认为这是一种非常惯用的用例类方法。它们主要用作数据容器,通常不包含任何行为。(也许你可以告诉一些关于你想用这个实现的事情的更多信息)不确定你的用例,但是如果你想让它工作,你需要像这样定义class
A
:
abstract case class A(x: Double, y: Double) extends Operation
但我不认为这是一种非常惯用的用例类方法。它们主要用作数据容器,通常不包含任何行为。(也许你可以告诉我更多关于你想通过这个实现的事情的信息)首先,你应该:
trait OperationPlus extends Operation
trait OperationMinus extends Operation
其次,您不能将A
定义为case类,因为这会自动定义伴生对象上的apply
方法,其中调用newa
(带参数)。由于错误的自我类型(您看到的错误),此调用失败
卸下外壳
。如果需要模式匹配,请自己定义一个提取器(不适用地实现):
首先,你应该:
trait OperationPlus extends Operation
trait OperationMinus extends Operation
其次,您不能将A
定义为case类,因为这会自动定义伴生对象上的apply
方法,其中调用newa
(带参数)。由于错误的自我类型(您看到的错误),此调用失败
卸下外壳
。如果需要模式匹配,请自己定义一个提取器(不适用地实现):
谢谢@tenshi,如果我将案例类抽象化,我将无法实例化它。我试图做的是一个经典的面向对象父类,每个子类定义一个方法。然而,这些方法可以被不同的层次结构重用,所以我想将其作为基本特征。我就是找不到如何提取它。@fracca您仍然可以通过混合一些操作来实例化它:newa(1.0,2.0)和operation减号
。但是在您的示例方法中,有些东西是抽象的,所以您需要定义它或使整个类抽象。或者,您可以在类A
中直接扩展operation减号
或OperationPlus
,而不将其声明为抽象。抽象案例类有效地保留了案例类加行为混合的优点。但是,因为something操作是基于A定义的,所以我需要重新定义字段x和y。谢谢@tenshi,如果我将case类抽象化,我将无法实例化它。我试图做的是一个经典的面向对象父类,每个子类定义一个方法。然而,这些方法可以被不同的层次结构重用,所以我想将其作为基本特征。我就是找不到如何提取它。@fracca您仍然可以通过混合一些操作来实例化它:newa(1.0,2.0)和operation减号
。但是在您的示例方法中,有些东西是抽象的,所以您需要定义它或使整个类抽象。或者,您可以在类A
中直接扩展operation减号
或OperationPlus
,而不将其声明为抽象。抽象案例类有效地保留了案例类加行为混合的优点。但是,因为something操作是基于A定义的,所以我需要重新定义字段x和y。