我想知道,这两者有什么区别:
class SomeClass(val a: Int)
//1
class Class1[T <: SomeClass] {
def method1(param1: T) = ....
}
//2
class Class2 {
def method1(param1: SomeClass) = ....
}
我想知道,这两者有什么区别:
class SomeClass(val a: Int)
//1
class Class1[T <: SomeClass] {
def method1(param1: T) = ....
}
//2
class Class2 {
def method1(param1: SomeClass) = ....
}
功能上?说明为什么某些 3rd-party 代码有可能加载这些类将执行以下操作:
class ThirdPatyClass(val a: Int) extends SomeClass(a) with ThirdPartyTrait
Class1[ThirdPartyClass]
可以使用(和具体化的对应)的实例,method1
其中将存在表单的类型绑定
[S <: ThirdPartyTrait]
而Class2
不能。
而且,当然,根据您在这些方法中所做的事情,您T
可以在.T
Class[_ <: T]
Class1.method1
通常,Class1
您为编译器(和开发人员)提供了param1
保留Class2
更多param1
关于SomeClass
.
编辑:从评论中回答问题 - 是的,是选择一种方法还是另一种取决于您的需要。如果您需要更多的灵活性和更多的静态类型信息,请使用泛型类型边界。如果没有,我会说你应该遵循YAGNI而不是弄乱你的 API。
Class2
既是类又是类型,而Class1
只是类。永远不会有带有 type 的值Class1
,尽管可以有任意数量的参数化类型(Class1[SomeClass]
, Class1[SomeSubClass1]
, Class1[SomeClassType2] 等),所有这些类型都具有相同的类,并且在运行时只能根据Class1[_]
类型来识别擦除。这有一些实际效果:
Class1
比Class2
.Class1
需要更多的思考,因为必须考虑方差问题。另一方面,因为Class1
是参数化的,所以很容易混合任意一组特征,并且知道它们都可以安全地应用于同一类型,而不需要任何公共继承或特殊等价方法。编译器将捕获不兼容的类型操作。
trait Trait1[T]
def method1: T // Method happens to do something safely compatible with SomeClass
}
trait Trait2[T <: SomeClass]
def method2: T
}
class NewClass[T <: SomeClass] extends Class1[T] with Trait1[T] with Trait2[T]