2

假设我有一个 A、B、C 类继承的 M 类:

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)

Wheretransform对每个子类型基本上都是一样的,只是结果对象的构造方式不同。

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

编辑

请注意,def transform[T<:M](t:T):T这不起作用。如果我们尝试返回 A、B 或 C,我们将收到以下错误消息。

A 类型的表达式不符合预期的 T 类型

B 类型的表达式不符合预期的 T 类型

C 类型的表达式不符合预期的 T 类型

编辑 2 也许关于我正在尝试做的一些更详细的信息:

transform(m:M) = {
    val P = Property P computed from m
    m match {
        case a:A => construct and return new A from a with property P
        case b:B => construct and return new B from b with property P
        case c:C => construct and return new C from c with property P
        case _ => error
    }
}

如果我这样做,那么我需要演员表:

val a1:A = transform(a0).asInstanceOf[A]
val b1:B = transform(b0).asInstanceOf[B]
val c1:C = transform(c0).asInstanceOf[C]

我想消除它。

4

2 回答 2

3

这很容易:

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)
于 2015-06-28T13:54:22.567 回答
2

这取决于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,编译器将只允许您调用。transformTransformer

于 2015-06-29T10:00:30.810 回答