问题描述
我定义了一个这样的类型类:
/** Type class */
trait Drivable[V <: Vehicle]{
def drive(v:V)
}
它请求Vehicle的子类型作为drive
函数的参数。现在,我正在尝试将此类型类用于Vehicle
本身。
/** ADT */
sealed trait Vehicle{
def drive[V <: Vehicle](implicit d: Drivable[V]): Unit = d.drive(this)
}
编译器抱怨:
Error:(15,74) type mismatch;
found : Vehicle.this.type (with underlying type Vehicle)
required: V
def drive[V <: Vehicle](implicit d: Drivable[V]): Unit = d.drive(this)
如果我强制将this
强制转换为V
def drive[V <: Vehicle](implicit d: Drivable[V]): Unit = d.drive(this.asInstanceOf[V])
但是我讨厌这样做。或者,如果我将它放在case类中,它也可以工作:
final case class Car(name:String) extends Vehicle {
def drive(implicit d: Drivable[Car]): Unit = d.drive(this)
}
但是想象我有很多case classes
,我必须在每个人中都重复一遍。
在基本特征中使用此类型类的正确方法是什么?
解决方法
将drive
用作扩展方法
sealed trait Vehicle
implicit class DrivableOps[V <: Vehicle](val vehicle: V) extends AnyVal {
def drive(implicit d: Drivable[V]): Unit = d.drive(vehicle)
}
或将V
设为特征的类型成员,而不是方法的类型参数
sealed trait Vehicle {
type V >: this.type <: Vehicle
def drive(implicit d: Drivable[V]): Unit = d.drive(this)
}
case class Bus() extends Vehicle {
override type V = Bus
}
case class Car() extends Vehicle {
override type V = Car
}
类型V
可以自动生成:
//libraryDependencies += "com.github.dmytromitin" %% "auxify-macros" % "0.8"
import com.github.dmytromitin.auxify.macros.self
@self sealed trait Vehicle {
def drive(implicit d: Drivable[Self]): Unit = d.drive(this)
}
@self case class Bus() extends Vehicle
@self case class Car() extends Vehicle