Scala-返回与作为参数传递的类型相同的类型

Scala-返回与作为参数传递的类型相同的类型,scala,generics,code-reuse,return-type,generic-variance,Scala,Generics,Code Reuse,Return Type,Generic Variance,假设我有一个类M,它由类a、B、C继承: abstract M A extends M B extends M C extends M 我想这样做: val a0:A = ... val b0:B = ... val c0:C = ... val a1:A = transform[A](a0) val b1:B = transform[B](b0) val c1:C = transform[C](c0) 其中,transform对每个子类型的作用基本相同,只是在结果对象的构造方式上有所不同

假设我有一个类M,它由类a、B、C继承:

abstract M
A extends M
B extends M
C extends M
我想这样做:

val a0:A = ...
val b0:B = ...
val c0:C = ...
val a1:A = transform[A](a0)
val b1:B = transform[B](b0)
val c1:C = transform[C](c0)
其中,
transform
对每个子类型的作用基本相同,只是在结果对象的构造方式上有所不同

我有一种不可能的预感,我需要复制代码并创建单独的转换方法,或者求助于类型转换。还是有更好的办法

编辑

请注意,
def transform[T这非常简单:

class M
class A extends M
class B extends M

def transform[T <: M](obj: T): T = {
    obj
}

val a0:A = new A
val a1:A = transform(a0)
val b0:B = new B
val b1:B = transform(b0)
M类
A类扩展了M
B类扩展了M类

def transform[T它取决于
transform
的实现。如果编译器清楚地知道
transform
保留了类型,那么@Dimitry的答案是有效的

如果您需要类型之间不太明显的(对编译器而言)关系,那么通常的方法是类型类模式

trait Transformer[T] {
  def transform(t: T) : T
}

def transform[T: Transformer](t: T) = implicitly[Transformer[T]].transform(t)

implicit object ATransformer extends Transformer[A] {
  def transform(a: A): A = ...
}
implicit object BTransformer extends Transformer[B] {
  def transform(b: B): B = ...
}

然后,您可以在特定对象中实现
A
/
B
/
C
的特定转换,并且编译器只允许您在隐式作用域中具有合适的
转换器的情况下调用
transform

也许我撞到了头,但
t>:M
意味着t是一个超类of M-M的任何超类-这在继承层次结构中是一种错误的方向?抱歉,打印错误。编辑了我的答案,试试这个代码。在我问这个问题之前,我已经试过了。不幸的是,这似乎不起作用(请参阅问题的编辑)。我已经试过了。如果它对您有效,那么我猜我与M匹配(请参阅上面的第二次编辑)根本不“明显”用@Imm的话来说,这足够让编译器在我的情况下工作了。很好的补充,但User1291告诉我,我的解决方案对他不起作用。有什么想法吗?很有趣……这比简单地重载转换方法有什么好处?@Dimitry是的,如果你正在构建自己的A/B/C,那么你需要像我一样的类型类模式建议这样做。@User1291优点是,如果调用
transform
的方法本身是泛型的(您只需包含typeclass约束
[T:Transformer]
),就可以使用这种方法。
class M
class A extends M
class B extends M

def transform[T <: M](obj: T): T = {
    obj
}

val a0:A = new A
val a1:A = transform(a0)
val b0:B = new B
val b1:B = transform(b0)
trait Transformer[T] {
  def transform(t: T) : T
}

def transform[T: Transformer](t: T) = implicitly[Transformer[T]].transform(t)

implicit object ATransformer extends Transformer[A] {
  def transform(a: A): A = ...
}
implicit object BTransformer extends Transformer[B] {
  def transform(b: B): B = ...
}