zoukankan      html  css  js  c++  java
  • 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群

    DT大数据梦工厂① :462923555
    DT大数据梦工厂②:437123764
    DT大数据梦工厂③ :418110145

    微信公众账号: DT_Spark
    王家林老师微信号: 18610086859
    王家林老师QQ: 1740415547
    王家林老师邮箱: 18610086859@126.com

    本视频由王家林老师, 亲自讲解, 完全通过代码实战把您带人大数据的时代.

    package com.parllay.scala.type_parameterizitor

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

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

    def main(args: Array[String]) {

    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) 了。
    */

  • 相关阅读:
    Spring核心之IoC
    【jmeter】jMeter使用Badboy录制Web测试脚本
    【jmeter】jmeter环境搭建
    【jmeter】Jmeter启动GUI界面出错
    【appium】keyevent的keycode
    !!!!!!!【unittest】unittest需要懂的的技术
    【unittest】unittest单元模块做assert
    【appium】根据UIAutomator定位元素
    【appium】根据class_name定位元素
    【appium】根据name定位元素
  • 原文地址:https://www.cnblogs.com/czh-liyu/p/4716087.html
Copyright © 2011-2022 走看看