Scala方差,上界和下界
时间:2020-02-23 14:41:50 来源:igfitidea点击:
差异是指复杂类型之间的子类型如何与其组成部分的子类型相关。
Scala支持泛型类的类型参数的方差注释。
Scala支持的差异注释类型为;
| Types | Definition | Scala Notation |
| Covariant | C[T’] is a subclass of C[T] | [+T] |
| Contravariant | C[T] is a subclass of C[T’] | [-T] |
| Invariant | C[T] and C[T’] are not related | [T] |
class Array[+X] {
def add[Y >: X](elem: Y): Array[Y] = new Array[Y] {
override def first: Y = elem
override def retrieve: Array[Y] = Array.this
override def toString() = elem.toString() + "\n" + Array.this.toString()
}
def first: X = sys.error("No elements in the Array")
def retrieve: Array[X] = sys.error("Array is empty")
override def toString() = ""
}
object ArrayTest extends App {
var a: Array[Any] = new Array().add("US");
//a = a.add(new Object())
a = a.add(56)
a = a.add(67.89)
println("Array elements added are: " + a)
}
注释+ X表示X只能在协变位置使用。
注释-X表示X只能在相反位置使用。
如果X是S的子类型,则Array [X]是S的子类型。
在此示例中,我们定义了协变类型参数X来定义方法add。
我们有一个多态方法,其中我们使用元素类型X作为add方法类型变量的下限,从而使X的方差与其声明为协变参数同步。
我们正在插入String,Integer和float类型的元素。
上限类型界限
类型上限X <:B声明类型变量X引用类型B的子类型。
考虑下面的示例。
trait Employee {
def EmployeeIdexists(x: Any): Boolean
}
case class EId(a: Int) extends Employee {
def EmployeeIdexists(x: Any): Boolean =
x.isInstanceOf[EId] &&
x.asInstanceOf[EId].a == a
}
object TestEmployee extends App {
def findEId[A <: Employee](d: A, ls: List[A]): Boolean =
if (ls.isEmpty) false
else if (d.EmployeeIdexists(ls.head)) true
else findEId[A](d, ls.tail)
val elist: List[EId] = List(EId(25), EId(26), EId(27), EId(28))
if ((findEId[EId](EId(28), elist)))
println("Employee Id exists")
else println("Employee Id does not exist")
}
本示例查找员工ID是否存在。
我们正在定义一个findEId方法,该方法创建一个整数列表并检查指定的ID是否包含在列表中。
下界
术语X>:B表示类型参数X或者抽象类型X引用类型B的超类型。
类型下限声明一个类型为另一种类型的超类型。
将scala类ListNode创建为;
case class ListNode[+T](h: T, t: ListNode[T]) {
def head: T = h
def tail: ListNode[T] = t
def prepend[U >: T](elem: U): ListNode[U] =
ListNode(elem, this)
}
我们正在创建类ListNode并定义prepend方法,其中T仅出现在协变位置。
U>:T指定抽象类型U是T的超类型。
类型变量T作为方法前缀的参数类型出现,此规则已损坏。
不过,借助下限类型,我们可以实现prepend方法。
现在创建一个scala对象为;
object LowerBoundTest extends App {
val empty: ListNode[Null] = ListNode(null, null)
val strList: ListNode[String] = empty.prepend("hello")
.prepend("world")
val anylist: ListNode[Any] = strList.prepend(12345)
println(strList)
println(anylist)
}

