继承与多态

来源:互联网 发布:fft算法的作用 编辑:程序博客网 时间:2024/06/05 08:36
什么是继承?
继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
什么是多态?
指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。我们可以用老虎这个词来称呼老虎,也可以用肉食动物来称呼老虎,这就是多态性。
怎么实现多态?
后期绑定、也叫运行时绑定、也叫动态绑定,RTTI(Run-Time Type Information)
在运行时根据对象的类型进行绑定。
一种语言想要实现后期绑定,就必须具有某种机制,以便在运行时能判断对象类型。
多态实现的简单顺序如下:
假设 有: Animals a=new Tiger(); a.getName();
第一步,虚拟机提取a实际类型(Animals )的方法表(每次调用之前都要搜索,这样编译器开销会很大,因此,编译器预先为每个类创建一个方法表,列出所有方法的签名和实际调用的方法,这样一来调用时,编译器查这张表就行了)。
第二步,虚拟机搜索定义方法名叫 “getName”签名的类。
第三步,虚拟机根据参数确定要调用的类。
第四步,虚拟机调用该getName方法。

具体如何实现RTTI请看下一章类型信息。
多态的表现形式是?
一种是父类与子类之间的重写
另一种是同类中的重载。
(这里回忆一下java的三大特征:封装,继承,多态。不要搞混了!)
什么是方法的重写?
子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。 如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。
静态方法也可以重写嘛?
从重写方法会有什么特点来看,我们是不能重写静态方法的。虽然就算你重写静态方法,编译器也不会报错。也就是说,如果你试图重写静态方法,Java不会阻止你这么做,但你却得不到预期的结果(重写仅对非静态方法有用)。重写指的是根据运行时对象的类型来决定调用哪个方法,而不是根据编译时的类型。让我们猜一猜为什么静态方法是比较特殊的?因为它们是类的方法,所以它们在编译阶段就使用编译出来的类型进行绑定了。使用对象引用来访问静态方法只是Java设计者给程序员的自由。我们应该直接使用类名来访问静态方法,而不要使用对象引用来访问。
第二个问题,方法重写和方法隐藏不同
public class JavaTest {
    public static void main(String[] args) {
        Animal a = new Cat();
        System.out.println(a.A);
        System.out.println(a.b);
        a.voice();
        a.method();
    }
}class Cat extends Animal {
    public int b = 4;
    public static int A = 4; public static void method() {
        System.out.println("猫");
    } public void voice() {
        System.out.println("猫叫");
    }
}class Animal {
    public int b = 0;
    public static int A = 0; public static void method() {
        System.out.println("动物");
    } public void voice() {
        System.out.println("动物叫");
    }
}
打印结果为:
0
0
猫叫
动物
首先了解一下什么是隐藏什么是覆盖,隐藏和覆盖的前提是要继承。
非静态的方法在子类中重写的话就是被覆盖,而静态的方法被子类重写的话就是隐藏。(另外静态变量和成员变量也是被隐藏的哦)
重写和隐藏的区别,这里要了解多态的实现,是使用了RTTI(run-time type identification)机制(运行期类型检查、动态绑定),当Animal的引用a指向子类Cat时,RTTI在运行期会自动确定该引用的真实类型,并且RTTI是只针对覆盖,不针对影藏,所以,静态变量 A 和 非静态变量 b 以及静态方法method() 均不通过RTTI,是哪个类的引用就调用谁的静态方法,成员变量,而这里是父类Animal的引用,所以直接调用父类Animal中的方法以及成员变量。所以静态方法 method()、 静态变量 A 和成员变量 b 打印结果全是父类中的。只用被覆盖的非静态方法voice()才打印子类的。 

0 0
原创粉丝点击