W.P*_*ill 8 generics polymorphism scala return-type
我有一个抽象的Scala类Base
,它有子类Derived1
和Derived2
.Base
定义一个函数f(),它返回与其实现类相同类型的对象.所以Derived1.f()
返回Derived1
并Derived2.f()
返回Derived2
.我如何在Scala中写这个?
这是我到目前为止所提出的.
package com.github.wpm.cancan
abstract class Base {
def f[C <: Base]: C
}
case class Derived1(x: Int) extends Base {
def f[Derived1] = Derived1(x + 1)
}
case class Derived2(x: Int) extends Base {
def f[Derived2] = Derived2(x + 2)
}
Run Code Online (Sandbox Code Playgroud)
这给出了以下编译器错误:
type mismatch;
[error] found : com.github.wpm.cancan.Derived1
[error] required: Derived1
[error] def f[Derived1] = Derived1(x + 1)
type mismatch;
[error] found : com.github.wpm.cancan.Derived2
[error] required: Derived2
[error] def f[Derived2] = Derived2(x + 2)
Run Code Online (Sandbox Code Playgroud)
此错误消息让我感到困惑,因为我认为com.github.wpm.cancan.Derived1
应该与Derived1
此上下文中的相同.
Tra*_*own 15
Randall Schulz指出了当前代码不起作用的原因之一.但是,使用F -bounded多态性可以得到你想要的东西:
trait Base[C <: Base[C]] { def f: C }
case class Derived1(x: Int) extends Base[Derived1] {
def f: Derived1 = Derived1(x + 1)
}
case class Derived2(x: Int) extends Base[Derived2] {
// Note that you don't have to provide the return type here.
def f = Derived2(x + 2)
}
Run Code Online (Sandbox Code Playgroud)
基本特征上的类型参数允许您在那里讨论实现类 - 例如,在返回类型中f
.
只是为了增加一个小的精度(非常好)特拉维斯·布朗回答:这不是C
在trait Base[C <: Base[C]]
你们提到实施阶级; 它只是坚持写作的惯例subclass extends Base[subclass]
,让你这样做.我不知道要提到这种类型.为了澄清我的意思,这个编译
trait Base[C <: Base[C]] { def f: C }
case class Derived1(x: Int) extends Base[Derived1] {
def f: Derived1 = Derived1(x + 1)
}
// a Derived2 where f returns Derived1!!
case class Derived2(x: Int) extends Base[Derived1] {
def f = Derived1(x + 2)
}
Run Code Online (Sandbox Code Playgroud)
现在,如果你将要实现的Base
是case类的实现,你可以通过自我类型绑定来实现:
trait Base[C <: Base[C]] { self: C =>
def f: C
}
case class Derived1(x: Int) extends Base[Derived1] {
def f: Derived1 = Derived1(x + 1)
}
// a Derived2 where f returns Derived1!!
// this won't compile now
case class Derived2(x: Int) extends Base[Derived1] {
def f = Derived1(x + 2)
}
Run Code Online (Sandbox Code Playgroud)