给出以下类别:
abstract class Foo[B]
abstract class Baz[B, F <: Foo[B]] {
def get(foo: F): B
// other methods
}
我讨厌在Baz
中需要两个类型参数,如果第一个是冗余的。我想写这样的东西:
abstract class Baz[F <: Foo[B]] {
def get(foo: F): B
}
我是否可以在不采用多个类型参数的情况下引用Baz中的B类型(属于F)?感觉应该有可能,但是我似乎无法弄清楚语法。
答案 0 :(得分:4)
您可以使B
成为类型成员而不是类型参数吗?
abstract class Foo { type B }
abstract class Baz[F <: Foo] {
def get(foo: F): F#B
// other methods
}
然后,如果同时需要type参数和type成员,则可以使用Aux-pattern
abstract class Foo { type B }
// Foo.Aux[B] instead of Foo[B]
object Foo {
type Aux[B0] = Foo { type B = B0 }
}
abstract class Baz[F <: Foo] {
def get(foo: F): F#B
// other methods
}
您可以使F
种类更多并且get
多态吗? (看起来像一种“无标签最终”方法。)
abstract class Foo[B]
abstract class Baz[F[X] <: Foo[X]] {
def get[B](foo: F[B]): B
// other methods
}
您可以将Foo
设为类型类吗?
abstract class Foo[F] {
type B
}
object Foo {
type Aux[F, B0] = Foo[F] { type B = B0 }
def instance[F, B0]: Aux[F, B0] = new Foo[F] { type B = B0 }
//instead of class F1 extends Foo[B1]
implicit val foo1: Aux[F1, B1] = instance
}
abstract class Baz[F](implicit val foo: Foo[F]) {
def get: foo.B
// other methods
}
或
abstract class Baz[F: Foo] {
val foo: Foo[F] = implicitly
def get: foo.B
// other methods
}
您可以将两个类型参数提取到新类中吗?
abstract class Foo[B]
abstract class Tuple {
type B
type F <: Foo[B]
}
abstract class Baz[T <: Tuple] {
def get(foo: T#F): T#B
// other methods
}
或
abstract class Baz[T <: Tuple](t: T) {
def get(foo: t.F): t.B
// other methods
}
答案 1 :(得分:2)
当第一个是多余的时,我讨厌在Baz中需要两个类型参数。
没有冗余。如果Baz
代码引用了2种不同的类型,那么我们需要为它们使用2种不同的名称(F
和B
或X
和Y
,或THIS
和THAT
都没关系)。
如果Baz
代码仅引用1种类型,但是该类型需要限制为Foo
已经实现的某种类型,则可以添加该限制:
class Baz[X](implicit ev: Foo[X]) { ...
这可以简化为:
class Baz[X: Foo] { ...
如果无法推断类型,并且您希望简化实例创建,则可以使用类型成员/别名。
abstract class Baz[B] {
type F = Foo[B]
def get(foo: F): B
}
但是将内容写出来通常更清楚。
abstract class Baz[B] {
def get(foo: Foo[B]): B
}
但是,这当然消除了子类型的可能性。