# scala-协变、逆变、上界、下界 原荐

jacksu

B是A的子类，A是B的父类。

##Scala的协变

``````    class Animal {}
class Bird extends Animal {}
class Animal {}
class Bird extends Animal {}
//协变
class Covariant[T](t:T){}
val cov = new Covariant[Bird](new Bird)
val cov2:Covariant[Animal] = cov
``````

cov不能赋值给cov2，因为Covariant定义成不变类型。

``````    class Animal {}
class Bird extends Animal {}
class Animal {}
class Bird extends Animal {}
//协变
class Covariant[+T](t:T){}
val cov = new Covariant[Bird](new Bird)
val cov2:Covariant[Animal] = cov
``````

##Scala的逆变

``````    class Animal {}
class Bird extends Animal {}
class Contravariant[-T](t: T) {
}
val c: Contravariant[Animal] = new Contravariant[Animal](new Animal)
val c2: Contravariant[Bird] = c
``````

##下界lower bounds

``````    class Animal {}
class Bird extends Animal {}
class Consumer[+T](t: T) {
def use(t: T) = {}
}
``````

``````    class Animal {}
class Bird extends Animal {}
class Consumer[+T](t: T) {
def get(): T = {new T}
}
``````

``````    class Animal {}
class Bird extends Animal {}
class Consumer[+T](t: T) {
def use[U >: T](u : U) = {println(u)}
}
``````

``````    class Animal {}
class Bird extends Animal {}
class Consumer[-T](t: T) {
def get[U <: T](): U = {new U}
}
``````

``````    class Animal {}
class Bird extends Animal {}
class Consumer[-S,+T]() {
def m1[U >: T](u: U): T = {new T} //协变，下界
def m2[U <: S](s: S): U = {new U} //逆变，上界
}
class Test extends App {
val c:Consumer[Animal,Bird] = new Consumer[Animal,Bird]()
val c2:Consumer[Bird,Animal] = c
c2.m1(new Animal)
c2.m2(new Bird)
}
``````

##View Bound <%

Scala还有一种视图绑定的功能，如

``````    class Bird {def sing = {}}
class Toy {}
class Consumer[T <% Bird]() {
def use(t: T) = t.sing
}
``````

``````    class Bird {def sing = {}}
class Toy {}
class Consumer() {
def use[T <% Bird](t: T) = t.sing
}
class Test extends App {
val c = new Consumer()
c.use(new Toy)
}
``````

``````    import scala.language.implicitConversions
class Bird {def sing = {}}
class Toy {}
class Consumer() {
def use[T <% Bird](t: T) = t.sing
}
class Test extends App {
implicit def toy2Bird(t: Toy) = new Bird
val c = new Consumer()
c.use(new Toy)
}
``````

##Context Bound

context bound在Scala 2.8.0中引入，也被称作type class pattern。 view bound使用A <% String方式，context bound则需要参数化的类型，如Ordered[A]。 它声明了一个类型A,隐式地有一个类型B[A],语法如下：

``````    def f[A : B](a: A) = g(a) // where g requires an implicit value of type B[A]
``````

``````    def f[A : ClassManifest](n: Int) = new Array[A](n)
``````

``````    def f[A : Ordering](a: A, b: A) = implicitly[Ordering[A]].compare(a, b)
``````

Scala的协变和逆变上界与下界

### 评论(5)

#### 引用来自“pseudo”的评论

scala里居然还有这种概念啊……学过相对论或者微分几何的应该知道逆变张量和协变张量是什么

Scala的协变covariant(+)，逆变contravariant(-)，上界(:)

u013063153
2017/11/09
0
0
Scala的协变(+)，逆变(-)，上界(:)

Scala的协变(+)，逆变(-)，上界(<:)，下界(>:) 协变covariant、逆变contravariant、不可变invariant 对于一个带类型参数的类型，比如 List[T]，如果对A及其子类型B，满足 List[B]也符合List[...

2015/08/02
0
0
Scala之类型参数化：Type Parameterization

Scala之类型参数化：Type Parameterization 本文原文出处: http://blog.csdn.net/bluishglc/article/details/52584401 严禁任何形式的转载，否则将委托CSDN官方维护权益！ 型变：Variance 型...

bluishglc
2016/09/19
0
0
Scala版的生产者消费者模型&泛型中的协变（Covariance）与逆变（Contravar...

class BoundedBufferA : ClassManifest {var in = 0var out = 0var n = 0 val elems = new ArrayA def put(x: A) = synchronized {while (n >= N) wait()elems(in) = xin = (in + 1) % Nn = ......

2012/07/03
0
0
Scala 语言学习之泛型（7）

==> 泛型类 ---> T 可以代表任意类型 ==> 泛型函数 ---> 类型参数放在方法名之后 ==> 类型的上界和下界（Upper Bounds 和 Lower Bounds） ---> 用来定义泛型变量的范围 ： ---> S <: T (上界......

2017/11/12
0
0
Kotlin 泛型 VS Java 泛型

JohnnyShieh
06/11
0
0
scala高阶函数

2016/04/18
49
0
Java泛型的协变、逆变和不变

JarryWell
07/11
0
0
Java中逆变与协变

Hosee
2016/02/25
159
0
Scala 高阶函数(high-order function)剖析

Scala 是一种函数式编程语言，也就是说每一个函数都是一个值。Scala 有很简洁的语法用于定义匿名函数、curry 化函数（curried function）、应用函数、偏函数以及嵌套函数等。函数式编程由数学...

Barudisshu
2015/06/30
0
0

Java基础——异常

31分钟前
0
0

34分钟前
0
0
SBT 常用开发技巧

SBT 一直以来都是 Scala 开发者不可言说的痛，最主要的原因就是官方文档维护质量较差，没有经过系统的、循序渐进式的整理，导致初学者入门门槛较高。虽然也有其它构建工具可以选择(例如 Mill...

joymufeng
39分钟前
0
0
HBase in Practice - 性能、监控及问题解决

40分钟前
1
0
ES18-JAVA API 批量操作

1.批量查询 Multi Get API public static void multiGet() {// 批量查询MultiGetResponse response = getClient().prepareMultiGet().add("my_person", "my_index", "1")// 查......

44分钟前
0
0
SpringBoot2.0使用health

1，引入actuator <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency> 2，application.properties ......

51分钟前
0
0

###编程规约 命名风格 【强制】代码中的命名均不能以下划线或美元符号开始，也不能以下划线或美元符号结束 【强制】代码中的命名严禁使用拼音与英文混合的方式，更不允许直接使用中文的方式。...

56分钟前
0
0

durban

0
0

LM_Mike

0
0
2018年7月23日课程

0
0