java中的多态及运用
多态属于面向对象语言的三大特性之一,简单说就是同一个对象在不同时刻表现出不同的形态。在java中,多态的运用需要有以下三个条件:
- 有继承/实现的关系
- 有方法重写
- 有父类引用指向子类对象
举个例子,我们建立一个动物类,如下:
public class Animals {
public void eat(){
System.out.println("动物吃肉");
}
}
我们在定义一个猫类,继承自动物类,如下:
public class cat extends Animals{
@Override//多态需要重写方法,我们重写eat方法
public void eat() {
System.out.println("猫吃鱼");
}
public void play(){
System.out.println("猫玩毛线球");
}
}
接下来,我们建立测试类,在其中运用多态建立对象:
public class Demo {
public static void main(String[] args) {
Animals a = new cat();
a.eat();
}
}
在main方法中,我们创建了一个cat的对象a,其引用父类类型,即父类引用指向子类对象,那么此时这个对象a的创建就运用了多态。最后,上面这个例子输出的结果就是
多态的成员访问特点
在编译时,我们看到的是多态对象的类型,即他的父类,如上面a对象的类型就是Animals,那么编译时,所调用的变量必须是Animals中有的,cat类中独有的变量不能被编译,会报错;而在我们调用的方法中,也需要在父类中有才能通过编译。
执行时,成员变量的值是父类中的成员变量的值,而成员方法因为有重写的缘故,优先执行子类中重写过的方法,否则执行父类中的成员方法。
总结:
对成员变量来说,编译和执行都看对象引用类型,如:
Animals a = new cat();
System.out.println(a.age);
这里对象a是cat类,但他的引用类型为它的父类Animals,因此编译和执行时都用的父类Animals中的成员变量age。
对成员方法来说,编译看的是引用类型的成员方法,但因为重写的缘故,执行时优先执行重写后的子类cat中的成员方法。
2021年5月29日更新
那么如果我们非要使用子类对象中的特有方法时,该怎么操作呢?我们可以使用类型强制转换,即向下转型,以上面的例子来说,我们要在main方法中调用子类对象中play方法,我们可以这样做:
Cat c= (Cat)a;
c.play();
System.out.println(a);
System.out.println(c);
我们可以看拿到,我们将一个Animals类型的通过强制转换变成了cat类型,那么cat类型的c变量当然就可以调用cat类中特有方法,我们再输出a和c的地址值,结果如下:
我们发现此时a和c 的地址值是相同,表示这是一同一个变量,至此,我们就可以做到在多态下使用子类特有的方法。
2021年5月30日更新
除了上述的通过继承实现对象的多态,还可以通过接口实现来实现对象的多态。接口是对动作的抽象化,而类是对对象的抽象化。
举例如下:
创建eating的接口,并提供抽象方法eat。
public interface eating {
public void eat();
}
创建cat类,这个类实现了eating接口。
public class Cat implements eating{
@Override
public void eat() {
System.out.println("猫现在学会吃饭了");
}
}
最后在main方法中,捅多态创建接口对象
public class InterfaceDemo {
public static void main(String[] args) {
eating c = new Cat();
c.eat();
}
}
这个就是通过接口实现来使用多态
结果如下:
总结:多态的形式主要有三种,具体类多态,抽象类多态,接口多态,后两种使用更加广泛
多态的前提:有继承或实现关系,有方法重写,有父(类/接口)引用只想子(类/实现)对象。
仅供个人学习使用,如有错误请指出,谢谢