立即注册 登录
About云-梭伦科技 返回首页

pig2的个人空间 https://www.aboutyun.com/?61 [收藏] [复制] [分享] [RSS]

日志

Scala中super总结

已有 2196 次阅读2016-11-14 10:11 | super

论在类的哪个地方,super 调用都是静态绑定的,但在特质中,它们是动态绑定的,因为在
特质定义时,尚且不知道它的超类是谁,因为它还没有“混入”,由于在特质中使用super
调用超类方法是动态绑定的,因此你需要对特质中相应的方法加上abstract 声明(虽然加上
了abstract 声明,但方法仍可以被具体定义,这种用法只有在特质中有效),以告诉编译器
特质中的该方法只有在特质被混入某个具有期待方法的具体定义的类中才有效。你需要非常
注意特质被混入的次序:特质在构造时顺序是从左到右,构造器的顺序是类的线性化(线性
化是描述某个类型的所有超类型的一种技术规格)的反向。由于多态性,子类的方法最先起
作用,因此越靠近右侧的特质越先起作用,如果最右侧特质调用了super,它调用左侧的特
质的方法,依此类推。


在 Java 或者 Scala 的类中,super.foo() 这样的方法调用是静态绑定的,也就是说当你在代码中写下 super.foo() 的时候就能明确是调用它的父类的 foo() 方法。然而,如果是在特质中写下了 super.foo() 时,它的调用是动态绑定的。调用的实现奖在每一次特质被混入到具体类的时候才被决定。

确切的讲,特质的 super 调用与混入的次序很重要,参照下面的例子说话:
val queue = (new BasicIntQueue with Incrementing with Doubling)

直截的讲就是超靠近后面的特质越优先起作用。当你调用带混入的类的方法是,最右侧特质的方法首先被调用。如果那个方法调用了 super,它调用其左侧特质的方法。可以这么认为,Doubling 的 super 指向了  Incrementing,Incrementing 的 super 指向了 BasicIntQueue。

来看个完整的实例实际体验一把,如果要帮助理解,最好应该实际运行一下这个实例

import scala.collection.mutable.ArrayBuffer

/**
 * @author Unmi
 */
object TestClient extends App {    
    val queue1 = (new BasicIntQueue with Incrementing with Doubling)
    queue1.put(2) //Doubling.put(2*2)->Incrementing.put(4+1)
    println(queue1.get()) //result is 5
    
    val queue2 = (new BasicIntQueue with Doubling with Incrementing)
    queue2.put(2) //Incrementing.put(2+1)->Doubling.put(2*3)
    println(queue2.get()) //result is 6
}

abstract class IntQueue {
    def get(): Int
    def put(x: Int)
}

class BasicIntQueue extends IntQueue {
    private val buf = new ArrayBuffer[Int]
    def get() = buf.remove(0)
    def put(x: Int) { buf += x }
}

trait Incrementing extends IntQueue {
    abstract override def put(x: Int) {
        super.put(x + 1)
    }
}

trait Doubling extends IntQueue {
    abstract override def put(x: Int) {
        super.put(2 * x)
    }
}

实例中两次声明 queue1 和 queue2 是采用了不同的顺序混入 Incrementing 和 Doubling 两个特质,执行的效果是不一样,输出分别是 5 和 6。这种对 super 的重新理解会带来冲击,同时很有可能在代码维护时调整混入的特质时引来些许的麻烦。

混入特质存在着一种线性化的次序关系,再来看一下这个线性化的例子:
class Animal
trait Furry extends Animal
trait HasLegs extends Animal
trait FourLegged extends HasLegs
class Cat extends Animal with Furry with FourLegged


下图是 Cat 类的继承层级和线性化次序的展示图

 

继承次序使用白色三角箭头表示,箭头指向超类,黑底箭头说明线性化次序,箭头指向 super  调用解决的方向。



 super和this使用区别

super和this两者都属于构造器的部分


一、使用方法:

   this: 1、this.属性  2、this.方法   3、this(参数)  

 注意----》(1)属性或者方法不能是静态的,因静态的方法或属性不属于类的实例!

   (2)属性只能是本类的属性,方法可以是父类的方法

        super:  1、super.方法   2、super(参数1,参数2,……)

注意 ----》(1)如果super和this关键字都在构造方法中出现,那么this一定是放在最前面


二、使用举例

1、新建父类:AnimalInfo.Java

public class AnimalInfo {
private String color;
private String type;

public AnimalInfo(){
System.out.println("父类的无参构造方法!");
}
public AnimalInfo(String color, String type) {
this.color = color;
this.type = type;
System.out.println("父类的有参构造方法结果:打印颜色:"+color+";类型:"+type);
}

/**
 * 重载:要求返回值类型、方法名称一致而参数列表必须不同,访问修饰符不限制
 * 
 */
public void eat(){
System.out.println("父类的吃方法!");
}
protected void eat(String width){}
void eat(String width,String height){}

/*动物叫方法*/
public void song(){
System.out.println("父类的叫方法!");
}
}

2、新建子类:DogInfo.java

public class DogInfo extends AnimalInfo {
    String name;

    /**

      *覆盖:要求方法名称必须一致,访问修饰符限制必须一致或者范围更宽
     */

    /*如果构造方法不添加访问修饰符,那么就是默认(default)*/
    DogInfo() {
    this("狗二");
    System.out.println("子类无参构造方法");
    super.eat();//如果遇到this关键字,它就必须承让了,放在第二行
   this.eat();
    }
    /**覆盖构造方法,覆盖只发生在构造方法中*/
    DogInfo(String input) {
    //必须放在构造方法的第一行
    super("blue","dog");
     // super(); //必须放在构造方法的第一行
       name = input;
   }

    private  DogInfo(String out,String in){ } 
    DogInfo(String out,String in,String error){  } 
}


3、新建测试类:TestMethod.java

public class TestMethod{

    public static void main(String args[]) {
//     AnimalInfo an=new AnimalInfo();
    DogInfo dog2 = new DogInfo();
    DogInfo dog1 = new DogInfo("狗一");
        System.out.println(dog1.name + ";" + dog2.name);
        /**打印结果:
       父类的有参构造方法结果:打印颜色:blue;类型:dog
父类的有参构造方法结果:打印颜色:blue;类型:dog
父类的吃方法!
父类的吃方法!
狗一;狗二
        */

    }

}






路过

雷人

握手

鲜花

鸡蛋

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 立即注册

关闭

推荐上一条 /2 下一条