自身类型

2017-02-06  本文已影响0人  风干鸡

自身类型

Scala里面有自身类型,这个东西相当于方法隐藏的this参数的类型。

有了这个东西,可以写出这样的代码。

class A {
  def fun1(): this.type = {
    this
  }
}

class B extends A{
  def fun2(): this.type = {
    print("b")
    this
  }
}

object Test{
  def main(args: Array[String]): Unit = {
    new B().fun1().fun2()
  }
}

而java就不可以这样,比如同样的代码,用Java写出来:

public class Test{
    public static void main(String[] args){
        new B().fun1().fun2();
                      ^ 这里会报错
    }
}

class A{
    A fun1() {
        return this;
    }
}

class B extends A{
    B fun2() {
        return this;
    }
}

因为fun1()的返回值类型是A而不是B,Java支持协变返回类型,但是要在子类中覆盖。

class B extends A{
    @Override
    B fun1() {
        return (B) super.fun1();
    }

    B fun2() {
        return this;
    }
}

这样功能虽然相同,但是很多余。

如果把方法当成函数,把隐藏的this参数展开,用静态方法来表示:

class A{
    static <E extends A> E fun1(E this$) {
        //do something whit this$
        return this$;
    }
}

这样就很清晰了,事实上this.type 就是隐藏this参数的类型参数,而他依据调用方法的对象来推导出返回值的类型。

上面的代码就可以改成:

public class Test{
    public static void main(String[] args){
        B b = new B();
        fun2(fun1(b));
    }
}

class A{
    static <T extends A> T fun1(T this$) {
        //do something whit this$
        return this$;
    }
}

class B extends A{
    static <T extends A> T fun2(T this$) {
        return this$;
    }
}

功能完全一致,但是他是静态方法不能用.调用,如果说写这样的代码就是为了方便链式调用的话,这样肯定是不符合要求的。

那么返回值就只能用泛型了(继承的时候需要手动指定类型参数)。

public class Test{
    public static void main(String[] args){
        new B().fun1().fun2();
    }
}

class A<T extends A<T>>{
    T fun1() {
        return (T) this;
    }
}

class B extends A<B> {
    B fun2() {
        return null;
    }
}

非常的难看。

上一篇下一篇

猜你喜欢

热点阅读