gpt4 book ai didi

Scala重写F有界多态中子类型的类型参数

转载 作者:行者123 更新时间:2023-12-04 19:03:33 26 4
gpt4 key购买 nike

我正在尝试创建一个特征 Entity它强制其子类型具有 2 个状态:TransientPersistent

trait EntityState
trait Transient extends EntityState
trait Persistent extends EntityState
trait Entity[State <: EntityState]

例如,一个子类,说 class Post[State <: EntityState] extends Entity[State] , 可以被实例化为 new Post[Persistent]或作为 new Post[Transient] .

接下来,我将向 trait Entity 添加一些方法。可以根据其 State 调用:
trait Entity[State <: EntityState] {
def id(implicit ev: State <:< Persistent): Long
def persist(implicit ev: State <:< Transient): Entity[Persistent]
}

解释一下,对于任何扩展 Entity 的类, 方法 id只能在类状态为 Persistent 时调用(即它已保存到数据库并已分配一个自动生成的 id)。

另一方面,方法 persist只能在类为 Transient 时调用(尚未保存到数据库中)。方法 persist用于将调用者类的实例保存到数据库和 返回 Persistent类的版本。

现在,问题是 我想要 persist 的返回类型成为调用者类的 .例如,如果我调用 persist在类 Post[Transient] 的实例上,它应该返回 Post[Persistent]而不是 Entity[Persistent] .

我四处寻找,发现一个叫做 F-Bounded Polymorphism 的东西。 .我正在尝试多种方法来调整它以解决我的问题,但仍然无法正常工作。这是我所做的:

第一次尝试:
trait Entity[State <: EntityState, Self[_] <: Entity[State,Self]] {
def id(implicit ev: State <:< Persistent): Long
def persist(implicit ev: State <:< Transient): Self[Persistent]
}


class Post[State <: EntityState] extends Entity[State, ({type λ[B] == Post[State]})#λ] {

def persist(implicit ev: <:<[State, Transient]): Post[State] = {
???
}
}

在类(class) Post上面,我使用 Eclipse 的自动完成来生成方法的实现 persist发现它的返回类型还是不对。

第二次尝试:
class Post[State <: EntityState] extends Entity[State, Post] {

def persist(implicit ev: <:<[State, Transient]): Post[Persistent] = {
???
}
}

有了这个,它似乎是正确的,除了它有一个编译错误:
[error] D:\playspace\myblog\app\models\post\Post.scala:14: kinds of the type arguments (State,models.post.Post) do not conform to the expected kinds of the type parameters (type State,type Self) in trait Entity.
[error] models.post.Post's type parameters do not match type Self's expected parameters:
[error] type State's bounds <: common.models.EntityState are stricter than type _'s declared bounds >: Nothing <: Any
[error] trait Post[State <: EntityState] extends Entity[State, Post] {

最佳答案

我相信这就是你想要做的:

trait Entity[State <: EntityState, Self[S<:EntityState] <: Entity[S, Self]] {
_: Self[State] =>

def id(implicit ev: State <:< Persistent): Long
def persist(implicit ev: State <:< Transient): Self[Persistent]
}


abstract class Post[State <: EntityState] extends Entity[State, Post] {
def persist(implicit ev: <:<[State, Transient]): Post[Persistent] = {
???
}
}

更新: _: Self[State] => part 是一个自类型注解。它说任何混合 Entity 的类特质 必须延长 Self[State] (不这样做会导致编译时错误)。如果我们删除这个自类型注释,我们可能会定义这样的东西,编译器不会眨眼:
abstract class User[State <: EntityState] extends Entity[State, Post] {
def persist(implicit ev: <:<[State, Transient]): Post[Persistent] = {
???
}
}

注意 User类扩展 EntitySelf type 参数设置为 Post (而不是 User )。就编译器而言,这是有效的,但肯定不是您的想法。
使用 self-type 注释,上面的代码不会编译:
<console>:12: error: illegal inheritance;
self-type User[State] does not conform to Entity[State,Post]'s selftype Post[State]
abstract class User[State <: EntityState] extends Entity[State, Post] {
^

关于Scala重写F有界多态中子类型的类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31097783/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com