Scala 泛型类型和方法

abstract class Stack[A] { 
  def push(x: A): Stack[A] = new NonEmptyStack[A](x, this) 
    def isEmpty: Boolean 
    def top: A 
    def pop: Stack[A] 
    val contents: T = _   //初始值:_ ,表示一个默认值,数字类型是0 ,boolean是false ,Unit是() (无参数无返回),其他是null
} 
class EmptyStack[A] extends Stack[A] { 
  def isEmpty = true
  def top = error("EmptyStack.top") 
  def pop = error("EmptyStack.pop") 
} 
class NonEmptyStack[A](elem: A, rest: Stack[A]) extends Stack[A] { 
  def isEmpty = false
  def top = elem 
  def pop = rest 
} 
  
val x = new EmptyStack[Int] 
val y = x.push(1).push(2) 
println(y.pop.top) 
  
def isPrefix[A](p: Stack[A], s: Stack[A]): Boolean = { 
  p.isEmpty || 
  p.top == s.top && isPrefix[A](p.pop, s.pop) 
} 
  
val s1 = new EmptyStack[String].push("abc") 
val s2 = new EmptyStack[String].push("abx").push(s1.top) 
println(isPrefix[String](s1, s2)) 

类型参数边界

  在用类型参数定义了一个抽象类Set[A]后,在实现中要用到比较(<>),但是不能确定A的具体类型,因此不能直接使用。一个解决办法就是对合法类型进行限制,对只含有方法<>的类型放行。在标准库里有一个特质Ordered[A],用来表示可比较的类型。现在可以强制要求这个类型为Ordered的子类型。可以通过给出一个上界(upper bound)的方式来解决这个问题:

abstract class Set[A] {
  def incl(x: A): Set[A]
  def contains(x: A): Boolean
}
// 传入的A类型参数必须是Ordered[A]的子类型
class EmptySet[A <: Ordered[A]] extends Set[A] {
	def contains(x: A): Boolean = false
	def incl(x: A): Set[A] = new NonEmptySet(x, new EmptySet[A], new EmptySet[A])
	// 在new NonEmptySet(...)时,没有写入类型参数。因为可以从返回值类型中推断出来。
}
class NonEmptySet[A <: Ordered[A]](elem: A, left: Set[A], right: Set[A]) extends Set[A] {
	def contains(x: A): Boolean =
		if (x < elem) left contains x
		else if (x > elem) right contains x
		else true
	def incl(x: A): Set[A] =
		if (x < elem) new NonEmptySet(elem, left incl x, right)
		else if (x > elem) new NonEmptySet(elem, left, right incl x)
		else this
}
// 先创建一个Ordered的子类
case class Num(value: Double) extends Ordered[Num] {
	def compare(that: Num): Int =
		if (this.value < that.value) -1
		else if (this.value > that.value) 1
		else 0
}

val s = new EmptySet[Num].incl(Num(1.0)).incl(Num(2.0))
s.contains(Num(1.5))

变化型注解(variance annotation)

“+”表示协变,“-”表示逆变。
C[+T]:如果A是B的子类,那么C[A]是C[B]的子类。
C[-T]:如果A是B的子类,那么C[B]是C[A]的子类。
C[T]:无论A和B是什么关系,C[A]和C[B]没有从属关系。

协变类型应该出现在协变位置,这些位置包括:类里值的参数类型;方法的返回值类型;以及其他协变类型中的参数。放在其他地方会被拒绝

class Array[+A] {
	def apply(index: Int): A
	def update(index: Int, elem: A)  // 可以通过下界(lower bounds)来解决这个问题
								^ covariant type parameter A
								  appears in contravariant position.
}
// 下界(Lower Bounds)
// B是A的父类
class Stack[+A] {
	def push[B >: A](x: B): Stack[B] = new NonEmptyStack(x, this)
}
原文地址:https://www.cnblogs.com/wwxbi/p/4176215.html