scala 内部类、路径依赖类型、类型投影

先回顾一下java的内部类

class Outter{

    public class Inner {}

    public void foo(Inner c){

        System.out.println(c);

    }

}

public class Main {

    public static void main(String[] args)throws Exception{

        Outter o1 = new Outter();

        Outter o2 = new Outter();

        Outter.Inner i1 = o1.new Inner();

        Outter.Inner i2 = o2.new Inner();

        o1.foo(i2);

    }

}

Outter类定义了内部Inner类,在main里创建了两个Inner实例

注意new内部类的时候用 Outter.Inner i1 = o1.new Inner();

前边必须限定外部对象;

class Outter {

    public class Inner{}

    public void test() {

        new Inner(); // 相当于this.new Inner(); 也可以写为Outter.this.new Inner();

    }

}

同样的事情翻译为scala代码:

scala> class A {

            class B;

            def foo(b:B) = println(b)

        }

scala> val a1 = new A

scala> val a2 = new A

scala> val b1 = new a1.B

scala> val b2 = new a2.B

在创建内部类的时候,语法上与java有所不同,不是 outter.new Inner() 而是 new outter.Inner(),看上去只是表象不同么?实际上,scala有很大差异,不同于java里 i1 和 i2 类型是相同的,否则 o1.foo(i2) 就不能执行了,scala里的 b1 和 b2 是不同的类型:

scala> a1.foo(b2)

:12: error: type mismatch;

a1.foo方法接受的参数类型为:a1.B,而传入的b2 类型是 a2.B,两者不匹配。

验证一下:

scala> typeOf[a1.B] == typeOf[a2.B]

res2: Boolean = false

确实是不一样的类型,它跟外部的实例相关,那个foo方法参数类型B的写法是缩写,省略了路径:

def foo(b: B) // 相当于 this.B 或 A.this.B

这里要引入一个概念:路径依赖类型(见最下面);比如上面的 A.this.B 就是一个路径依赖类型,B 前面的路径 A.this 随着不同的实例而不同,比如 a1 和 a2 就是两个不同的路径,所以a1.B 与 a2.B也是不同的类型。

那现在的问题来了,怎么让 a1.foo 方法可以接收 b2 参数 ?

class A {

    class B;

    def foo(b:B)  // 接收所有的B类型实例,而不只是foo的调用者实例(a1)路径下B类型的对象        println(b)

}

这又引出一个概念:类型投影(type projection)

在scala里,内部类型(排除定义在object内部的),想要表达所有的外部类A实例路径下的B的type(类型),即对 a1.B 和 a2.B 类型找一个共同的父类型,这就是类型投影,用 A#B的形式表示。

        A#B

        / \

      /  \

    a1.B  a2.B

这样,我们只要修改一下 foo 方法里的参数类型

def foo(b: A#B)

就可以调用 a1.foo(b2) 了。

路径依赖类型的路径完整写法

路径不是类型,而是类似某种位置。

1) 内部类定义在object里面,路径:package.object.Inner

object Singleton {

    class Inner

}

val x = new p1.p2.p3.Singleton.Inner

2) 内部类定义在class

//2.1) 直接在外部类中使用内部类型,路径:this 或 Outter.this

class A {

    class B

    val b = new B // 相当于 A.this.B

//2.2) 在子类中使用父类的内部类型,路径:super 或 Child.super

class A  { class B }

class C extends A { val x = new super.B } // 相当于 C.super.B

//2.3) 在其他类中使用,路径:outter(外部类实例)

class A  { class B }

class C {

    val a = new A

    val x = new a.B 

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容

  • Scala与Java的关系 Scala与Java的关系是非常紧密的!! 因为Scala是基于Java虚拟机,也就是...
    灯火gg阅读 3,444评论 1 24
  • pyspark.sql模块 模块上下文 Spark SQL和DataFrames的重要类: pyspark.sql...
    mpro阅读 9,453评论 0 13
  • 密密枝杈欲扫天 碧澄空明尘云无 试问谁把天公洗 寰宇原是春雨来(润) (改一) 密密枝杈欲扫天 碧澄空明尘云无 试...
    第二个自由的石头阅读 304评论 0 0
  • 如果这个世界上有后悔药,卡梅隆·温克莱沃斯和泰勒·温克莱沃斯这对双胞胎兄弟一定会毫不犹豫地来上一颗。2002年12...
    倾曼阅读 352评论 0 2
  • 你干什么呢
    蒋依珊阅读 154评论 0 0