自身类型
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;
}
}
非常的难看。