5

Type System of Scala: Covariant, Contravariant, and PECS Rule

 2 years ago
source link: https://jyzhu.top/2021/10/25/Type-System-of-Scala-Covariant-Contravariant-and-PECS-Rule/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Type System

What are types:

  • 意义的逻辑含义
  • 一个契约,要求所有成员有共同的特性
  • 所有值、变量都有type
  • 所有对象object都有type
  • 所有class、trait都type

value types & reference types

  • 有9种value types,它们不能为空:Byte Short Char Int Long Float Double Boolean Unit
  • 其他都是reference types:objects functions 等等

Type Hierarchies

image-20211022140614737image-20211022140614737

WEAK CONFORMANCE

image-20211022140142393image-20211022140142393
  • 和Java类似,前面type的都可以赋值转化成后面的type(typecast)
  • 数、字符字面量,都可以赋值给 Byte Short and Char

Subtype

  • 子类可以被当做父类

    val s: Student = new SmartStudent // 如此可以。s仍然是一个Student类,但它拥有SmartStudent的属性和方法
  • S是T的子类,记作∶𝑆<∶𝑇, 读作 S is a T and satisfies all properties that T does,so S can be treated as T

可以把S赋值给T的三种情况:

  1. 𝑆 primitive-widens to 𝑇 : widening is like Int converted to Double, is done implicitly
  2. 𝑆 primitive-narrows to 𝑇 : narrowing is like Double to Int, needs conversion
  3. 𝑆 <∶ 𝑇

Type Inference

Type inference is a technique for determining the type of some entity without explicitly specifying it

谨慎使用🤔

GENERICS, PARAMETRIC POLYMORPHISM & VARIANCE

想要通用化一个程序,可能是需要它可以处理不同的类型的参数。那么就可以把参数类型也作为一个参数传入,就是type parameter。表示为:

[T]

这样就会遇到subtype定义的问题。==a box of T should be able to both store and produce a T.==

假如GummyBear是Sweet的子类,但下面这两个都是错的:

val b: Box[GummyBear] = new Box[Sweet](new Sweet) // wrong
// 因为上述b需要可以 存 且 提供box中的类:
b.value = new GummyBear // ok
val a: GummyBear = b.value // not ok!

val b: Box[Sweet] = new Box[GummyBear](new GummyBear) // wrong
// 因为上述b需要可以 存 且 提供box中的类:
b.value = new Sweet // not ok!
val a: Sweet = b.value // ok

PECS Rule - Producer: Extends; Consumer: Super

  1. if you need a box that Produces T, use a box of anything that Extends T

    def produceFromBox(b: Box[_ <: Sweet]): Sweet = b.value

    covariant: S<:TC[S]<:C[T]

    class Box[+T](val value: T) // make Box covariant in T
    val b: Box[Sweet] = new Box[GummyBear](new GummyBear) // ok now
  2. if you need a box that Consumes T, use a box of anything that is Super of T

    def putInBox(b: Box[_ >: GummyBear], s: GummyBear) = { 
    b.value = s
    }

    contravariant: S<:TC[T]<:C[S]

    class Monster[-T] { // make Monster contravariant in T
    def eat(t: T) = println(t)
    }
    val m: Monster[GummyBear] = new Monster[Sweet] // ok now

VARIANCE OF FUNCTION TYPES

I2<:I1,R2<:R1I1=>R1<:I2=>R2

for example, 一个function接收AnyRef,返回Subtring,那它就是这个function的子类:接收Sweet(<: AnyRef),返回String(>: Substring):

AnyRef => Substring <: Sweet => String

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK