有父母时:
abstract class Parent {
def something(arg: ???): Parent = ???
}
和
class Child extends Parent {}
我想要
val updatedChild = new Child().something(...)
updatedChild
的类型为Child
,而不是类型为Parent
,这可能吗?
答案 0 :(得分:2)
一种实现方法是参数化父对象:
abstract class Parent[T <: Parent[T]] {
def something(arg: Foo): T
}
class Child(val foo: String) extends Parent[Child] {
def something(arg: String) = return new Child(arg)
}
有时,您还可以使用this.type
:
class Parent {
def something(arg: Foo): this.type = this
}
class Child {
override def something(arg: Foo) = this
}
但是后一种方法仅在您要返回的所有内容是this
(this.type
不是Parent
或Child
而是只有一个实例-this
)。
答案 1 :(得分:1)
看来您可以做到:
class Parent[THIS <: Parent[THIS]] {
def something: THIS
}
这似乎可行。
我不确定这是否是您应该做的事情。
答案 2 :(得分:1)
以下是实际上是编译的提案:
abstract class Parent[Repr <: Parent[Repr]] {
def something(arg: Int): Repr
}
这是您可以做到的,至少没有明确建议不要这样做。标准收藏库经常使用它,例如IterableLike作为这种F界多态性的典型示例。
答案 3 :(得分:0)
安德烈(Andrey)和迪玛(Dima)的答案都涵盖了仅使用oo模式解决问题的一种方法。
但是我想指出另一种称为 typeclasses (在函数式语言中更常见)的方法,如果您打算编写通用函数,这将很有帮助使用您的界面。
首先,有一个接口而不是父类,该接口描述了可以对类型类的实例执行的操作。
trait Typeclass[T] {
def something(t: T)(arg: Foo): T
}
然后,您将定义类型,这一次它们不扩展任何父类,因此不必重写任何内容。
class Child {
...
}
现在,您必须证明您的类型是类型类的实例。
(一个常见的实现方式是在类的伴随对象中)。
object Child {
implicit final val ChildTypeclass: Typeclass[Child] = new Typeclass[Child] {
override def something(child: Child)(arg: Foo): Child = ???
}
}
最后,定义一个通用方法,该方法可以在任何类型T上操作,只要该类型的实例是该类型的实例即可。
def generic[T](t: T, arg: Foo)(implicit tt: Typeclass[T]): T =
tt.something(t)(arg)
奖金,如果您想恢复“点符号” ,则可以向Typeclass添加Ops模式。
object syntax {
object typeclass {
implicit final class TypeclassOps[T](val t: T) extends AnyVal {
final def something(arg: Foo)(implicit tt: Typelcass[T]) =
tt.something(t)(arg)
}
}
}
import syntax.typeclasss._
def generic[T: Typelcass](t: T, arg: Foo): T
t.something(arg)
val newChild = generic(new Child, new Foo)
// newChild: Child = ???
此外,一种常见的方法是在您的类中定义something
方法,并且typeclass实例将调用转发给该类中定义的方法,这样您就可以在{{1 }},而不必放置所有类型类的机器。
我必须说,这对于非常高级的抽象很有用,您计划为这些抽象提供许多类型的实例((甚至是您控制范围之外的类型,如任何标准集合类型),并且编写非常可以在任何这些函数上运行的通用函数。
如果不是这样,则F边界类型似乎是更合理的解决方案。