【发布时间】:2016-11-09 15:59:01
【问题描述】:
所以这是 this Java question 到 scala 的一个相当直接的端口
我们有一堆采用通用参数的特征,如下所示:
trait Ident { }
trait Container[I <: Ident] {
def foo(id: I): String
}
trait Entity[C <: Container[I], I <: Ident] {
def container: C
def foo(id: I) = container.foo(id)
}
这可行,但有点笨拙,因为在定义实体的子类时,我们必须提供 Ident 的类型和 Container 的类型。实际上,仅 Container 的类型本身就足够了类型信息:
class MyIdent extends Ident { }
class MyContainer extends Container[MyIdent] { }
class MyEntity extends Entity[MyContainer,MyIdent] { }
// ^^^^^^^ shouldn't really be necessary
使用存在类型可以避免 Entity 需要两个参数...但是当然你以后不能引用它。
trait Entity[C <: Container[I] forSome { type I <: Ident }] {
def container: C
def foo(id: I) = container.foo(id)
// ^^^ complains it has no idea what 'I' is here
}
同样将事物转换为使用成员类型也行不通...
trait Ident { }
trait Container {
type I <: Ident
def foo(id: I): String
}
trait Entity {
type C <: Container
def container: C
def foo(id: C#I) = container.foo(id)
// ^^ type mismatch
}
那么有谁知道 Scala 中是否有一个优雅的解决方案来解决这个问题?
【问题讨论】:
-
我认为答案与 Java 版本不会有太大不同。没有办法在不丢失类型参数的情况下省略类型参数。
-
是否可以选择将
container设为val? -
@MichaelZajac 因此,在“MyEntity”的定义中,提供给 Entity 的第二个参数是多余的:除了“MyIdent”之外,您根本没有其他可能的类型可以使用,实际上任何其他类型都会给出编译错误。当然,能否避免 Scala 中的冗余是另一个问题:-)
-
检查this answer,了解我在回答中提出的类似内容如何导致不健全
标签: scala scala-generics