我有一个抽象类,将以多种不同的方式实现。我正在尝试创建一个方法,可以将这些实现中的任何一个作为参数,并返回相同类型的新实例。我试图通过传递"工厂"来实现这种行为。函数到产生抽象类型的新对象的方法(将在每个实现者中适当地设置)。
我试图将我遇到的问题分解为以下代码:
我的父抽象类:
abstract class Parent(val x: Int) {
type Self <: Parent
def factory: Int ⇒ Self
def me = "Parent"
}
Child类的一个示例:
class Child(x: Int) extends Parent(x) {
type Self = Child
override def factory: Int ⇒ Self = {
(v: Int) ⇒ new Child(v)
}
override def me = "Child"
}
我尝试使用Self
类型参数来确保factory
方法生成正确类型的对象。
现在方法本身:
object Parent {
def transform[T <: Parent](input: T#Self, factory: (Int ⇒ T#Self)): T#Self = {
//do stuff with input
input.me
val result = 123
factory(result)
}
}
现在,当我尝试实际连线时:
class Transformer[T <: Parent] {
var everyone: List[T#Self] = List.empty
def start() = {
val updated = for (e ← everyone) yield {
Parent.transform[T](e, e.factory)
}
everyone = updated
}
}
当我尝试将工厂传递给transform方法
时出现编译错误 Type mismatch, expected (Int) => T#Self, actual (Int) => Parent.this.Self
我尝试了各种各样的方法来实现这一点,但没有运气。我对此仍然很陌生,所以我可能(很可能)尝试在这里做一些疯狂的事情。一个更好的选择将非常感激,但我仍然有兴趣看看是否有可能让这样的东西工作。最终目标是让transform
方法生成与参数提供的完全相同类型的新实例。
非常感谢任何帮助。谢谢!
答案 0 :(得分:1)
我试图使用Self类型参数来确保 factory方法生成一个正确类型的对象。
这让我想起了tpolecat的Returning the "Current" Type in Scala:
我有一个类型层次结构...如何声明一个返回“当前”类型的超类型方法?
我们可以将该帖子中讨论的F-Bounded Types方法调整为Parent
和Child
层次结构:
trait Parent[A <: Parent[A]] { this: A =>
def x: Int
def factory: Int ⇒ A
def me = "Parent"
}
class Child(override val x: Int) extends Parent[Child] {
override def factory = (v: Int) ⇒ new Child(v)
override def me = "Child"
}
class OtherChild(override val x: Int) extends Parent[OtherChild] {
override def factory = (v: Int) ⇒ new OtherChild(v)
override def me = "OtherChild"
}
object Parent {
def transform[A <: Parent[A]](input: A): A = {
//do stuff with input
input.me
val result = 123
input.factory(result)
}
}
然后,在Bonus Round: How do we deal with collections?
部分之后,您的Transformer
会变成这样:
class Transformer {
import scala.language.existentials
var everyone = List[A forSome { type A <: Parent[A] }](new Child(1), new OtherChild(2))
def start() = {
val updated = everyone.map(Parent.transform(_))
everyone = updated
}
}