美文网首页Java 之旅
初级09 - 面向对象:多态

初级09 - 面向对象:多态

作者: 晓风残月1994 | 来源:发表于2019-08-03 15:55 被阅读0次

面向对象的三大基本原则之一 ——多态。多态赋予了你的程序无与伦比的强大功能,是面向对象的灵魂!


面向对象的三大特征:

  • 封装
  • 继承
  • 多态

1. 什么是多态?

这不是多态:

Person p1 = new Person();

下面是多态!Man 和 Woman 都是 Person 的子类:

Person p2 = new Man();
Person p3 = new Woman();

这就体现了对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
也因为一个子类类型的对象永远也是一个父类类型的对象,因此,当声明一个父类型时,总可以传递一个子类型对象。

多态性可以理解为一个事务的多种形态,= 赋值的右边有多种形态的对象来满足左边的需求。

2. 多态的使用

有了对象的多态性以后,在编译期,只能调用父类中声明的方法,但在运行期,实际执行的是子类重写父类后的方法。

  • 实例方法默认是多态的,在运行时根据this来决定调用哪个方法,而静态方法没有多态;
  • 参数是静态绑定,接收者是动态绑定;
  • 多态只对方法的接收者生效;
  • 多态只选择接收者的类型, 不选择参数的类型;
  • 例如:HashSet.addAll()
  • 静态方法的调用是通过在编译器静态绑定的,而实例方法的调用是在运行时动态绑定的
  • 多态是运行时行为

假设子类分别覆盖了父类的eat()walk()

Person p2 = new Man();
p2.eat();
p2.walk();

那么上面这样写是ok的,在编译期,这两个方法指的仍是父类Person的实例方法,运行时,子类对象接收到了方法调用的消息(同时可能还有方法的参数),其作为接收者要进行响应,发现子类进行了重写,于是动态调用重写后的方法。

接着这个思路,如果对p2调用只有子类Man中才存在的实例方法,在编译阶段会报错,因为编译时认为p2 属于赋值操作左边的类型,认为是Person类型,而Person并没有定义站着尿尿这个方法。

p2.站着尿尿();

结论

  • 编译时,看左边;运行时,看右边。
  • 多态的使用前提:
    • 类的继承关系
    • 方法的重写

3. 虚拟方法调用(多态的情况下)

子类中重写了父类方法后,在多态情况下,将此时父类的方法称为虚拟方法,在运行时,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的,所以比较虚。

在编译时是父类类型,运行时成了对子类类型上的方法调用,这个过程也称为动态绑定

借用一张尚硅谷免费资源中的PPT:


多态

4. 设计模式实战:策略模式

策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

使用了工厂方法的User(注意这个类不是策略模式必须的,或者说无关):

    private String name;
    private boolean vip;

    private User(String name, boolean vip) {
        this.name = name;
        this.vip = vip;
    }

    public static User vip(String name) {
        return new User(name, true);
    }

    public static User dios(String name) {
        return new User(name, false);
    }

    public String getName() { return name; }

    public boolean isVip() { return vip; }
}

接下来属于策略模式。

一个需要调用这组算法策略的使用者PriceCalculator

public class PriceCalculator {
    // 使用策略模式实现三个策略:
    // NoDiscountStrategy 不打折
    // Discount95Strategy 全场95折
    // OnlyVipDiscountStrategy 只有VIP打95折,其他人保持原价

    public static int calculatePrice(DiscountStrategy strategy, int price, User user) {
         return strategy.discount(price, user); // 实际执行的是子类重写后的方法
    }

    public static void main(String[] args) {
        User user = User.dios("wangpeng");
        System.out.println("用户名:" + user.getName());
        // 使用什么策略就传入什么策略
        int price = calculatePrice(new Discount95Strategy(), 10000, user);
        System.out.println("实际价格:" + price);
    }
}

策略的父类DiscountStrategy

public class DiscountStrategy {
    // 虽然正常情况下这个基类中的策略都会被某个具体策略给Override,但我认为目的有二:
    // 1. 被子类覆盖从而实现多态调用
    // 2. 用来兜底,抛出个异常
    public int discount(int price, User user) {
        throw new UnsupportedOperationException();
    }
}

没有折扣的NoDiscountStrategy

public class NoDiscountStrategy extends DiscountStrategy {
    @Override
    public int discount(int price, User user) {
        return price;
    }
}

打95折的Discount95Strategy

public class Discount95Strategy extends DiscountStrategy {
    @Override
    public int discount(int price, User user) {
        return (int)(price * 0.95);
    }
}

Vip独享的打折策略OnlyVipDiscountStrategy

public class OnlyVipDiscountStrategy extends DiscountStrategy {
    @Override
    public int discount(int price, User user) {
        if (user.isVip()) {
            return (int) (price * 0.95);
        } else {
            return price;
        }
    }
}

策略模式和模板方法模式有些类似,二者的界限在于:父类中是否包含“骨架”逻辑

策略模式的父类中几乎没有代码(大多数情况是个抽象方法),但是模版方法模式的父类中有一个“模板方法”,包含很多“骨架”逻辑代码。


参考文章:
Java中为什么静态方法不能被重写?为什么静态方法不能隐藏实例方法?

相关文章

  • 初级09 - 面向对象:多态

    面向对象的三大基本原则之一 ——多态。多态赋予了你的程序无与伦比的强大功能,是面向对象的灵魂! 面向对象的三大特征...

  • java面向对象,多态,抽象,接口

    day09笔记【java面向对象,多态,抽象,接口】 1 多态的概述及其代码体现 A:多态(polymorphic...

  • Java基础day08笔记:多态|多态中成员的特点|多态的应用示

    01-面向对象(多态-概念) 接下来说一下面向对象的第三个特征:多态。 何为多态呢? 其实...

  • 宅男知识大补丸 学多态 认包包

    java零基础入门-面向对象篇(十) 多态 面向对象的三大特征,封装,继承我们讲完了,这次来讲多态。 多态就是指一...

  • OC面向对象—多态

    OC面向对象—多态 OC面向对象—多态 一、基本概念 多态在代码中的体现,即为多种形态,必须要有继承,没有继承就没...

  • Java学习day-07:面向对象

    一、面向过程和面向对象 1.面向对象与面向过程的区别: 面向对象具有三大特征;封装,继承,多态;面向对象与面向过程...

  • Kotlin入门学习(二)

    新的篇章 面向对象 面向对象-封装 面向对象-继承 面向对象-抽象类和多态 接口 委托和代理 by关键字 委托...

  • 对象和面向对象的介绍

    对象分为 面向对象和基于对象: 面向对象:面向对象定义: 可以创建自定义类型、很好的支持继承和多态。面向对象的语言...

  • C#之面向对象基础篇

    面向对象编程:简称OOP 面试题:什么是面向对象? 答:封装,继承,多态即为面向对象 面相对象的方法: 面向对象的...

  • 面向对象

    面向对象有3大特性:封装、继承、多态1、介绍面向对象编程 面向对象编程(Object Oriented Progr...

网友评论

    本文标题:初级09 - 面向对象:多态

    本文链接:https://www.haomeiwen.com/subject/maocdctx.html