繁体   English   中英

多态Scala返回类型

[英]Polymorphic Scala return type

我有一个抽象的Scala类Base ,它有Derived1Derived2子类。 Base定义了一个函数f(),它返回与其实现类相同类型的对象。 所以Derived1.f()返回Derived1Derived2.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)
}

这给出了以下编译器错误:

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)

此错误消息让我感到困惑,因为我认为com.github.wpm.cancan.Derived1应该与此上下文中的Derived1相同。

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)
}

基本特征上的类型参数允许您在那里讨论实现类 - 例如,在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)
}

现在,如果所有你将要作为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)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM