gpt4 book ai didi

scala - T需要处于协变和逆变位置时的方差

转载 作者:行者123 更新时间:2023-12-02 03:06:18 24 4
gpt4 key购买 nike

这是我的问题,我有一个这样定义的类型类:

trait Alterer[T] {
def alter(t: T): T
}

object Alterer {
implicit val stringPrinter = new Alterer[String]{
override def alter(s: String) = "hi " + s
}
}

object Alter {
def alter[T](obj: T)(implicit alterer: Alterer[T]) = alterer.alter(obj)
}

val bob2 = Alter.alter("bob") // hi bob

现在我想为其他类型定义隐式实例。但我希望能够为父类(super class)型定义。 Any 作为父类(super class)型的示例:

case class Person(name: String, age: Int)

implicit val anyPrinter = new Alterer[Any]{
override def alter(a: Any) = ("hi any " + a.toString)
}

Alter.alter(Person("joe", 34))

这不会编译,因为如果我想让一个 Alterer[Any] 被视为一个 Alterer[Person],我的 T 类型需要是逆变的。

所以我会做类似的事情:

trait Alterer[-T] {
def alter(t: T): T
}

如果 alter 方法不返回 T 也没关系。编译器在这里提示,因为 T 返回类型不在逆变位置。

有办法解决吗?

谢谢

最佳答案

为此您需要两个类型参数,一个用于逆变输入,一个用于协变输出。

trait Alterer[-T, +U] {
def alter(t: T): U
}

然后你可以声明一个

  implicit val stringPrinter = new Alterer[String, String]{
override def alter(s: String) = "hi " + s
}

对于字符串或

implicit val anyPrinter = new Alterer[Any, String]{
override def alter(a: Any) = ("hi any " + a.toString)
}

将 Any 转换为字符串并添加 "hi any "

如果您想在输入和输出之间强制执行子类型关系,您可以使用在其构造函数中接受子类型证据的抽象类来代替您的特征。

abstract class Alterer[-T, +U](implicit ev: U <:< T) {
def alter(t: T): U
}

<:<在 predef 中定义并强制 U 是 T 的子类型。

此更改后此代码的其余部分保持不变。

关于scala - T需要处于协变和逆变位置时的方差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42585266/

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