继承与多态

xiaoxiao2021-02-27  462

什么是继承? 继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。 什么是多态? 指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。我们可以用老虎这个词来称呼老虎,也可以用肉食动物来称呼老虎,这就是多态性。 怎么实现多态? 后期绑定、也叫运行时绑定、也叫动态绑定,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()才打印子类的。 
转载请注明原文地址: https://www.6miu.com/read-1058.html

最新回复(0)