zoukankan      html  css  js  c++  java
  • java中的多态

    # 原创,转载请留言联系

    面向对象有三大特性:继承、封装、多态。

    继承与封装都比较容易理解,那么应该理解多态呢?

    多态,其实就是一个事物的多种形态。例如,一只猫,你可以叫它一只猫,也可以叫它一只动物。

    多态在java中是怎么体现的呢?

    需要满足三个前提:

    1.要有继承关系

    2.要有方法重写

    3.父类引用指向子类对象

    示例:

    public class Demo {
        public static void main(String[] args){
            Animal a = new Cat();    // 父类引用子类对象。猫可以是动物
            a.eat();
        }
    }
    
    class Animal{
        public void eat(){
            System.out.println("动物吃东西");
        }
    }
    
    class Cat extends Animal{    // 有继承关系
        public void eat(){       // 有方法重写
            System.out.println("猫吃鱼");
        }
    }

    这就是多态的经典例子。最重要的是父类引用子类对象。

    • 多态中的成员访问特点

    1.成员变量

    编译看左边,运行看左边

    public class Demo2 {
        public static void main(String[] args){
            Dad d = new Son();
            System.out.println(d.num);
        }
    }
    
    class Dad{
        int num = 10;
        public void show(){
            System.out.println("Dad");
        }
    }
    
    class Son extends Dad{
        int num = 20;
        public void show(){
            System.out.println("Son");
        }
    }

    输出结果是10

    2.成员方法

    编译看左边,运行看右边

    public class Demo2 {
        public static void main(String[] args){
            Dad d = new Son();
            d.show();
        }
    }
    
    class Dad{
        int num = 10;
        public void show(){
            System.out.println("Dad");
        }
    }
    
    class Son extends Dad{
        int num = 20;
        public void show(){
            System.out.println("Son");
        }
    }

    输出结果是:Son

    3.静态方法

    编译看左边,运行看左边

    public class Demo2 {
        public static void main(String[] args){
            Dad d = new Son();
            d.show();    // 相当于Dad.show()
        }
    }
    
    class Dad{
        int num = 10;
        public static void show(){
            System.out.println("Dad");
        }
    }
    
    class Son extends Dad{
        int num = 20;
        public static void show(){
            System.out.println("Son");
        }
    }

    输出结果:Dad

     

    • 向上转型与向下转型

    1.向上转型。

    向上转型其实就是父类引用子类对象。

    public class Demo2 {
        public static void main(String[] args){
            Dad d = new Son();  // 向上转型
        }
    }
    
    class Dad{
        int num = 10;
        public void show(){
            System.out.println("Dad");
        }
    }
    
    class Son extends Dad{
        int num = 20;
        public void show(){
            System.out.println("Son");
        }
    
        public void play(){
            System.out.println("玩耍");
        }
    }

    2.向下转型。

    如上面的例子所示,如果我们想要打印子类的num,调用子类的play()方法时,使用d.num打印的是父类的num值,而且d.play()直接出错了,因为父类没有play()方法,编译的时候不能通过。

    有什么解决方案呢?(访问子类独有的属性与方法)

    如果对象是Son类的对象就没有这些问题了。

    所以我们要向下转型。(这就是多态的弊端)

    示例:

    public class Demo2 {
        public static void main(String[] args){
            Dad d = new Son();
            Son s = (Son) d;    // 向下转型
            System.out.println(s.num);
            s.play();
        }
    }
    
    class Dad{
        int num = 10;
        public void show(){
            System.out.println("Dad");
        }
    }
    
    class Son extends Dad{
        int num = 20;
        public void show(){
            System.out.println("Son");
        }
    
        public void play(){
            System.out.println("玩耍");
        }
    }

    输出结果:

    20

    玩耍

    我们为什么要转型来转型去呢?直接Son s = new Son();不就好了吗?

    别急,来看看多态的好处就知道了。

     

    • 多态的好处

    假如有这么一个场景。

    class Animal{
        public void eat(){
            System.out.println("动物吃东西");
        }
    }
    
    class Cat extends Animal{    // 有继承关系
        public void eat(){       // 有方法重写
            System.out.println("猫吃鱼");
        }
    }
    
    class Dog extends Animal{
        public void eat(){
            System.out.println("狗吃骨头");
        }
    }

    如果你需要创建10个猫对象,并且调用eat()方法,原始做法是这样的:

    public class Demo {
        public static void main(String[] args){
            Cat c1 = new Cat();
            c1.eat();
            Cat c2 = new Cat();
            c2.eat();
            ......
        }

    然后你觉得很麻烦,你写了一个方法来改善它,

    public class Demo {
        public static void main(String[] args){
            method(new Cat());
            method(new Cat());
        }
        public static void method(Cat c){
            c.eat();
        }
    }

    这时候,又有需求,你要创建10个Dog对象,并调用eat()方法。

    你不得已,又写了一个方法:

    public class Demo {
        public static void main(String[] args){
            method(new Cat());
            method(new Cat());
            method2(new Dog());
            method2(new Dog());
        }
        public static void method(Cat c){
            c.eat();
        }
        public static void method2(Dog d){
            d.eat();
        }
    }

    这时候,又有一大堆需求,又新增猪类,鸡类,鸭类,继承Animal......你不再想写方法了。这时候多态的作用就来了。

    多态改善后:

    public class Demo {
        public static void main(String[] args){
            method(new Cat());
            method(new Cat());
            method(new Dog());
            method(new Dog());
        }
        public static void method(Animal a){
            a.eat();
        }
    }

    这就是多态的好处了,可以提高代码的扩展性。

    • 最后总结

    开发的时候很少在创建对象的时候用父类引用指向子类对象,直接创建子类对象更方便,可以使用子类中特有的属性与方法。当作参数的时候用多态最好,因为扩展性强。

  • 相关阅读:
    leetcode刷题 557~
    Unity正交相机智能包围物体(组)方案
    Embedded Browser(ZFBrowser)使用相关问题
    Unity性能优化
    sipp的使用
    Elment清除表单验证,防止报错小技巧
    git常用命令(干货)
    文本单词one-hot编码
    86. 分隔链表 链表
    5638. 吃苹果的最大数目 优先队列
  • 原文地址:https://www.cnblogs.com/chichung/p/10228991.html
Copyright © 2011-2022 走看看