文档章节

关于Scala的路徑依赖类型(Path-dependent type)

mj4738
 mj4738
发布于 2011/11/25 18:44
字数 990
阅读 908
收藏 0

         咋看这个术语,有点吓倒。其实不是什么新东西,也是讲关于内部类和外部类的事,不过两者有点区别。在Scala中,内部类和外部类的一些行为特性和Java差不多。 请看如下的Scala代码:

class Outer {
    private val x = 10
    class Inner {
        private val y = x + 10
    }
}

val outer = new Outer
val inner =  new outer.Inner
// inner变量可以显式声明类型
val inner: outer.Inner = new outer.Inner

 内部类Inner可以存取外部类成员(包括private成员),但外部类不能存取内部类的private成员. 内部类之所以能存取外部类的成员,是因为内部类隐含地持有外部类的实例。这点和Java是一样的,上述的代码可以用Java语言来表达: 

public class Op {

    public void test1(){
        Outer outer  = new Outer();
        Outer.Inner inner = outer.new Inner();
        System.out.println(inner);
    }

    public static void main(String[] args) {
        Op op = new Op();
        op.test1();
    }
}

class Outer {
    private int x = 10;
    class Inner {
        private int y = x + 10;
    }
}

注意Java和scala在创建成员内部类时的细微差别。

        Scala的内部类比Java的内部类具有更多特性,因此Scala引入了路径依赖类型(Path-dependent type)的概念。像outer.Inner这样的类型就称为路径依赖类型。所谓路径,指的就是参考外部类所建立的实例的名称。 就outer.Inner这个类型来说,路径为outer。更重要的是,不同路径代表不同的类型。比如:

val o1 = new Outer
val o2 = new Outer
val i1 =  new o1.Inner
val i2 =  new o2.Inner

上述的i1,i2分别引用了不同类型的实例,其中i1所引用的实体类型是o1.Inner, i2引用的实体类型是o2.Inner。假如你尝试把o1.Inner的实例赋值给声明为o2.Inner类型的变量,编译器会报错:

val o1 = new Outer
val o2 = new Outer
val i: o2.Inner = new o1.Inner   // 编译错误,类型不匹配

注意: 路径依赖的是路径的名称,与路径所引用的实例无关,请看例子: 

val o1 = new Outer
val o2 = o1
val i1: o1.Inner = new o1.Inner
val i2: o2.Inner = new o1.Inner   // 编译错误。尽管o2和o1引用同一个实例,但o1.Inner和o2.Inner是不同的,Scala编译器只根据路径名进行区分

事实上, o1.Inner和o2.Inner都是Outer#Inner的子类型, 请看例子
val o1 = new Outer
val o2 = new Outer
val i1: Outer#Inner = new o1.Inner
val i2: Outer#Inner = new o2.Inner

 路径依赖类型可以被继承,请看例子

val o = new Outer
class Some extends o.Inner
val oi: Outer#Inner = new Some

 注意:Outer#Inner是不能被继承的

 此外,路径依赖类型所在的路径必须是不可变的值。例如

var o1 = new Outer
val i = new o1.Inner   // 编译错误。因为o1是var

这也很好理解,如果o1是var,那么他的类型将是不确定的,从而导致其路径依赖类型也不确定。

一般地,x0.x1.x2...xn.T是路径一类类型,只要满足:

a) x0 是不可变值(即x0是val所声明的变量)

b) x1, x2, ..., xn 都是不可变的属性

c) T 是xn内部类 

 

下面看一个负责的例子:

class Food

class Fish extends Food {
    override def toString = "魚"
}

abstract class Animal {
    type F <: Food
    def eat(f: F)
}

class Cat extends Animal {
    type F = Fish
    def eat(fish: Fish) {
        println("吃" + fish)
    }
}

val cat1 = new Cat
val cat2 = new Cat
cat1.eat(new cat1.F)  // 吃魚
cat2.eat(new cat2.F)  // 吃魚

对于Cat类而言,F是其类型成员之一, 但这里 cat1.F和cat2.F代表相同的类型,也就是说你可以把一个cat2.F类型的实例传递给一个声明为cat1.F类型的变量. 实际上,上述代码的最后四行等价于以下的代码:

type F1 = Fish
type F2 = Fish
cat1.eat(new F1)   // 吃魚
cat1.eat(new F2)   // 吃魚

当然new Cat#F也是合法的

说了这么多,你们觉得这种特性有什么用途?如果你知道,请评论一下。

本文转载自:http://caterpillar.onlyfun.net/Gossip/Scala/PathDependentType.html

mj4738

mj4738

粉丝 295
博文 489
码字总数 119327
作品 0
崇明
高级程序员
私信 提问
【Scala】Cake模式和依赖注入

依赖注入(Dependency Injection)和控制反转(Inversion of Control) Dependency Injection & Inversion of Control是Martin Fowler在2004年所提出來的一个概念,Martin Fowler在这篇文章中...

JasonDing
2016/03/11
0
0
The type XXX cannot be resolved. It is indirectly

在Eclipse中遇到The type XXX cannot be resolved. It is indirectly referenced from required .class files错误.....,查找的解决办法如下: 一: It is indirectly referenced from required......

猴亮屏
2014/06/05
0
0
如何简单地创建复杂神经网络?—— DeepLearning.scala 2.0.0发布了

今天,DeepLearning.scala 2.0.0发布了。 DeepLearning.scala是个简单的框架,能以面向对象和函数式编程范式创建复杂的神经网络。 DeepLearning.scala运行在JVM上。既可以用于单独的JVM应用和...

jobthoughtworks
2017/07/26
236
0
C++箴言:理解 typename 的两个含义

  问题:在下面的 template declarations(模板声明)中 class 和 typename 有什么不同? template<class T> class Widget; // uses "class"template<typename T> class Widget; // uses ......

不必在乎朕是谁
2012/10/04
0
0
PHP获取当前文件路径,上层目录路径

取的現在檔案、目錄、上層目錄 於 test.php 內, 要做取得路徑、目錄等, 可見下述: 取得 路徑 + 檔名 (要取得 /var/www/project/test.php) * echo FILE; 取得 檔名 (要取得 test.php) * echo...

小果果x
2014/12/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

jquery通过id显示隐藏

var $div3 = $('#div3'); 显示 $div3.show(); 隐藏 $div3.hide();

yan_liu
今天
3
0
《乱世佳人》读书笔记及相关感悟3900字

《乱世佳人》读书笔记及相关感悟3900字: 之前一直听「荔枝」,后来不知怎的转向了「喜马拉雅」,一听就是三年。上班的时候听房产,买房了以后听装修,兴之所至时听旅行,分手后听亲密关系,...

原创小博客
今天
3
0
大数据教程(9.6)map端join实现

上一篇文章讲了mapreduce配合实现join,本节博主将讲述在map端的join实现; 一、需求 实现两个“表”的join操作,其中一个表数据量小,一个表很大,这种场景在实际中非常常见,比如“订单日志...

em_aaron
今天
3
0
cookie与session详解

session与cookie是什么? session与cookie属于一种会话控制技术.常用在身份识别,登录验证,数据传输等.举个例子,就像我们去超市买东西结账的时候,我们要拿出我们的会员卡才会获取优惠.这时...

士兵7
今天
3
0
十万个为什么之为什么大家都说dubbo

Dubbo是什么? 使用背景 dubbo为什么这么流行, 为什么大家都这么喜欢用dubbo; 通过了解分布式开发了解到, 为适应访问量暴增,业务拆分后, 子应用部署在多台服务器上,而多台服务器通过可以通过d...

尾生
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部