如果您愿意诉诸反射,您可以混合使用名义类型和结构类型:
import scala.language.reflectiveCalls
// A structural type exploiting the fact that all tuples have a _1 field
type IntComponent = { val _1: Int }
def add(list: List[Product with IntComponent], item: Product with IntComponent): List[Product with IntComponent] = {
if(list.isEmpty || list.head._1 > item._1) item :: list
else add(list.tail, item)
}
这种组合Product with IntComponent
并不是绝对必要的,IntComponent
就足够了。但是,这种组合为您提供了更多的安全性,并且它允许您使用Product
if 需要时声明的字段和方法。
这为您提供了相当多的静态类型安全性:
add(Nil, (1, "foo", null)) // ok
add(Nil, ("foo", 0)) // error
// error: type mismatch;
// found : String("foo")
// required: Int
add(List[Product with IntComponent](Tuple1(1), Tuple2(-1, true)), (0, "yes"))
// Explicit type annotation required, error otherwise
// found : List[Product with Serializable]
// required: List[Product with this.IntComponent]
这种方法的明显弱点是,您可以潜入任何 a 的对象,Product with IntComponent
例如
case class FakeTupleA(_1: Int)
add(Nil, FakeTupleA(99)) // ok
如果没有Product
要求,以下内容也可以工作:
add(Nil, new FakeTupleB(99))
// error: type mismatch;
// found : this.FakeTupleB
// required: Product with this.IntComponent