`
edge
  • 浏览: 66763 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Scala概述(五)抽象(2.1、2.2)

阅读更多

路径依赖类型(Path-dependent types 不知道AbsCell绑定的类型情况下,也可以对其进行访问。下面这段代码将一个cell的值恢复成为其初始值(init),而无需关心cell值的类型是什么。

def reset(c: AbsCell): unit = c.set(c.init)

为什么可以这样做呢?因为c.init的类型是c.T,而c.setc.T=>unit类型的函数,因此形参与实参类型一致,方法调用是类型正确的。

c.T是一个路径依赖类型的例子,通常来讲,这种类型的形式是:x1.x2.….xn.Tn>0),x1,…,xn是不可变的值,而Txn的类型成员。路径依赖类型是Scala的一个新颖的特性,其理论基础是vObj calculus[36]

路径依赖类型要依靠其前缀路径的不可变性,下面给出一个违反了不可变性的例子:

var flip = false

def f(): AbsCell = {

flip = !flip

if (flip) new AbsCell { type T = int; val init = 1 }

else new AbsCell { type T = String; val init = "" }

}

f().set(f().get) // illegal!

在上例中,每一次调用f()分别返回intString类型的值,因此最后一句是错误的,因为它要将String类型的值赋给一个int值的cellScala类型系统禁止这种调用,因为f().get的类型是f().T,而这不是一个有效类型,因为f()不是一个有效路径。

类型选择与单例类型(Type selection and singleton typesJava中,类型定义可以嵌套,嵌套类型用其外部类型做前缀的形态表示。在Scala中,则通过“外部类型#内部类型”(Outer#Inner)的方式来表示,“#”就称作类型选择(Type Selection)。从概念上说,这与路径依赖类型(例如:p.Inner)不同,因为p是一个值,不是一个类型。进一步而言,Outer#t也是一个无效表达式,如果t是一个定义在Outer中的抽象类型的话。

实际上,路径依赖类型可以被扩展成为类型选择,p.t可以看做是p.type#t,这里p.type就称作单例类型,仅代表p所指向对象的类型。单例类型本身对于支持方法调用串接很有作用,考虑如下代码:C有一个incr方法,对其值+1,其子类D由一个decr方法,对其值-1

class C {

protected var x = 0

def incr: this.type = { x = x + 1; this }

}

class D extends C {

def decr: this.type = { x = x - 1; this }

}

从而我们可以将相关调用串接起来:

val d = new D; d.incr.decr

如果没有this.type这个单例类型,上述调用是非法的,因为d.incr的类型应该是C,但C并没有decr方法。从这个意义上说,this.type类似于Kim Brucemytype[29]的一个协变的使用方式。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics