scala – 从抽象特征方法返回相同类型
发布时间:2020-12-16 09:54:57 所属栏目:安全 来源:网络整理
导读:让我们说我们有一个特征,它有一些价值观和一些操作. trait Foo { type Self : Foo val x: Int def withX(x: Int): Self} 这是使用抽象类型实现的.我们在Self上有一个绑定类型,可以像这样实现它: case class Foo1(x: Int) extends Foo { type Self = Foo1 de
让我们说我们有一个特征,它有一些价值观和一些操作.
trait Foo { type Self <: Foo val x: Int def withX(x: Int): Self } 这是使用抽象类型实现的.我们在Self上有一个绑定类型,可以像这样实现它: case class Foo1(x: Int) extends Foo { type Self = Foo1 def withX(x: Int) = copy(x = x) } 那样就好.我们可以使用该方法,我们看到该类型是静态保留的. scala> Foo1(10).withX(5) res0: Foo1 = Foo1(5) 当我们想要具有特征类型的操作而不是具体类型时,问题开始: object Foo { //Error:(13,43) type mismatch; //found : f.Self //required: A // def setFive[A <: Foo](f: A): A = f.withX(5) } 好吧,我们做不到,因为编译器不知道Foo#Self将被分配给什么类型.但我们知道它是同一类型. 当然使用丑陋的方法工作正常: object Foo { // Ugly type signature def setFiveValid[A <: Foo](f: A): A#Self = f.withX(5) // Another ugly type signature def setFiveValid2[A <: Foo](f: A): f.Self = f.withX(5) } 他们都没有非常清楚地表达意图. 我们可以使用类型类来解决它. case class Foo2(x: Int) trait FooOps[A] extends Any { def a: A def withX(x: Int): A } object Foo2 { implicit class Foo2Ops(val a: Foo2) extends AnyVal with FooOps[Foo2] { def withX(x: Int) = a.copy(x = x) } } object Foo { // View bounds approach. def setFiveValid3[A <% FooOps[A]](f: A): A = f.withX(5) } 然而这仍然非常嘈杂. 有没有更好的方法来实现setFive? 编辑1 自我类型的主要问题是这样的事情: Error:(24,11) type mismatch; found : app.models.world.WObject.WorldObjUpdate[self.Self] => app.models.world.WObject.WorldObjUpdate[self.Self] (which expands to) app.models.game.events.Evented[(app.models.world.World,self.Self)] => app.models.game.events.Evented[(app.models.world.World,self.Self)] required: app.models.world.WObject.WorldObjUpdate[self.Self] => app.models.game.events.Evented[(app.models.world.World,Self)] (which expands to) app.models.game.events.Evented[(app.models.world.World,Self)] identity ^ 然后再次采用奇怪的签名和样板: def attackReachable( data: WObject.WorldObjUpdate[Self] ): WObject.WorldObjUpdate[data.value._2.Self] 解决方法
你可以走“F-bounded quantication”之路:
trait Foo[F <: Foo[F]] { def withX(x: Int): F } object Foo { def setFive[F <: Foo[F]](f: F): F = f.withX(5) } 我成功地使用了这个,但它的代价是不得不写F<:Foo [F]]. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |