Scala 深刻淺出實戰經典 第52講:Scala中路徑依賴代碼實戰詳解

王家林親授《DT大數據夢工廠》大數據實戰視頻 Scala 深刻淺出實戰經典(1-64講)完整視頻、PPT、代碼下載:
百度雲盤:http://pan.baidu.com/s/1c0noOt6
騰訊微雲:http://url.cn/TnGbdC
360雲盤:http://yunpan.cn/cQ4c2UALDjSKy 訪問密碼 45e2
土豆:http://www.tudou.com/programs/view/jeikRw_tlBM/
優酷:http://v.youku.com/v_show/id_XMTI4NDI4NTkwOA==.html?from=s1.8-1-1.2
愛奇藝:http://www.iqiyi.com/w_19rrx9i29p.html#vfrm=2-3-0-1
騰訊視頻: http://v.qq.com/boke/page/s/0/u/s01598wtqzu.html
技術愛好者尤爲是大數據愛好者 能夠加DT大數據夢工廠的qq羣html

DT大數據夢工廠① :462923555
DT大數據夢工廠②:437123764
DT大數據夢工廠③ :418110145java

微信公衆帳號: DT_Spark
王家林老師微信號: 18610086859
王家林老師QQ: 1740415547
王家林老師郵箱: 18610086859@126.com微信

本視頻由王家林老師, 親自講解, 徹底經過代碼實戰把您帶人大數據的時代.大數據

package com.parllay.scala.type_parameterizitorui

/**
* Created by richard on 15-8-6.
*/this

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

def main(args: Array[String]) {scala

val outer = new Outer
val inner = new outer.Inner
val inner2 : outer.Inner = new outer.Inner翻譯

val o1 = new Outer
val o2 = new Outer視頻

//如下是會報錯的
//val i: o2.Inner = new o1.Inner

//正確的使用方法是
val i: Outer#Inner = new o1.Inner

}

}

/**
* 先回顧一下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實例,注意建立內部類的時候

Outter.Inner i1 = o1.new Inner();
在用new建立內部類時,前邊必須限定外部對象(內部類實例必需要訪問到外部對象引用):o1;
若是是在 Outter類內部這個外部引用能夠省略,它默認會用傳遞外部this引用。

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)
<console>:12: error: type mismatch;
found : a2.B
required: a1.B
按照方法的提示: 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也是不一樣的類型。路徑依賴類型的路徑完整寫法:

1) 內部類定義在object裏面,路徑:package.object.Inner

object Singleton {
class Inner
}

val x = new p1.p2.p3.Singleton.Inner
2) 內部類定義在class/trait 裏

//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
}
那如今的問題來了,怎麼讓 a1.foo 方法能夠接收 b2 參數 ?

class A {
class B;
def foo(b:B) // 接收全部的B類型實例,而不僅是foo的調用者實例(a1)路徑下B類型的對象
println(b)
}
這又引出一個概念:類型投影(type projection)

在scala裏,內部類型(排除定義在object內部的),想要表達全部的外部類A實例路徑下的B類型,
即對 a1.B 和 a2.B及全部的 an.B類型找一個共同的父類型,這就是類型投影,用 A#B的形式表示。

A#B
/ \
/ \
a1.B a2.B
這樣,咱們只要修改一下 foo 方法裏的參數類型

def foo(b: A#B)就能夠調用 a1.foo(b2) 了。 */

相關文章
相關標籤/搜索