一、多态的概念

  在面向对象语言中,多态是指在一棵继承树中的类中可以有多个同名但不同方法体及不同形参的方法。通常有两种途径实现多态:方法的重载和覆盖。

  多态性允许以统一的风格处理已存在的变量及相关的类。多态性使得向系统里增加新功能变得容易。继承性和多态性是降低软件复杂性有有效技术。

二、实现多态

  多态(polymoph)指的是“执行期间(而非编译期间)”判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。多态也叫动态绑定,也叫迟绑定。

  多态的存在有三个必要条件:

  1. 要有继承
  2. 要有方法重写
  3. 父类引用指向子类对象
    package com.duotai;
    /**
    * 狗狗类,宠物的子类
    */
    public class Dog extends Pet {
    private String strain="哈士奇";// 品种
    //无参构造方法
    public Dog(String name,int health,int love,String strain) {
    super(name,health,love);
    this.strain = strain;
    System.out.println("dog类构造方法");
    }
    public String getStrain() {
    return strain;
    }
    public void setStrain(String strain) {
    this.strain = strain;
    }
    //重写父类方法
    public void print() {
    System.out.println("宠物的自白:\n我的名字叫" +
    this.getName() + ",我的品种是" + this.getStrain()+",我的健康值是" + this.getHealth()
    + ",我和主人的亲密程度是" + this.getLove() + "。");
    }
    public void toHospital(){
    if(this.getHealth()<60){
    System.out.println("给狗狗打针、吃药");
    this.setHealth(60);
    }
    }
    }
    package com.duotai;
    /**
    * 企鹅类
    */
    public class Penguin extends Pet {
    private String sex="Q仔";// 企鹅性别
    //构造方法
    public Penguin(String name,int health,int love,String sex) {
    super(name,health,love);
    this.sex = sex;
    System.out.println("penguin类构造方法");
    }
    public String getSex() {
    return sex;
    }
    public void setSex(String sex) {
    this.sex = sex;
    }
    //重写父类方法
    public void print() {
    System.out.println("宠物的自白:\n我的名字叫" +
    this.getName() + ",我的性别是" + this.getSex()+",我的健康值是" + this.getHealth()
    + ",我和主人的亲密程度是" + this.getLove() + "。");
    }
    public void toHospital(){
    if(this.getHealth()<50){
    System.out.println("给企鹅吃药、疗养");
    this.setHealth(70);
    }
    }
    }
    package com.duotai;
    /**
    * 宠物类,狗狗和企鹅的父类
    */
    public class Pet {
    private String name = "无名氏";// 昵称
    private int health = 100;// 健康值
    private int love = 20;// 亲密度
    /**
    * 无参构造方法
    */
    public Pet() {
    System.out.println("父类无参构造方法");
    }
    /**
    * 有参构造方法
    * @param name 昵称
    */
    public Pet(String name,int health,int love) {
    this.name = name;
    this.health = health;
    this.love = love;
    System.out.println("父类有参构造方法");
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public int getHealth() {
    return health;
    }
    public void setHealth(int health) {
    if(health<0||health>100){
    System.out.println("健康值应该在0至100之间,默认值为60");
    this.health=60;
    return;
    }
    this.health = health;
    }
    public int getLove() {
    return love;
    }
    public void setLove(int love) {
    if(love<0||love>100){
    System.out.println("亲密度应该在0至100之间,默认值为15");
    this.love=15;
    return;
    }
    this.love = love;
    } /**
    * 输出宠物信息
    */
    public void print() {
    System.out.println("宠物的自白:\n我的名字叫" +
    this.name + ",我的健康值是" + this.health
    + ",我和主人的亲密程度是" + this.love + "。");
    }
    public void toHospital(){
    }
    }
    package com.duotai;
    /*
    * 主人类
    */
    public class Master {
    // //给狗狗看病方法
    // public void cure(Dog dog){
    // if(dog.getHealth()<60){
    // System.out.println("给宠物打针、吃药");
    // dog.setHealth(60);
    // }
    // }
    // //给企鹅看病方法
    // public void cure(Penguin pgn){
    // if(pgn.getHealth()<60){
    // System.out.println("给宠物吃药、疗养");
    // pgn.setHealth(70);
    // }
    // }
    //给宠物看病
    public void cure(Pet pe){
    pe.toHospital();
    }
    }
    package com.duotai;
    //测试类
    public class Test {
    public static void main(String[] args) {
    // 1、创建宠物对象pet并输出信息
    // Pet pet = new Pet("苏苏",99,60);
    // pet.print();
    Master master = new Master(); //实例化主人对象
    // 2、创建狗狗对象dog并输出信息
    //Dog dog = new Dog("丫丫",45,40,"牧羊犬");
    Pet pdog = new Dog("丫丫",45,40,"牧羊犬"); //向上转型
    master.cure(pdog);
    pdog.print();
    // 3、创建企鹅对象pgn并输出信息
    // Penguin pgn = new Penguin("果果",85,20,"Q妹");
    // pgn.print();
    //同一引用类型 不同的实例
    Pet ppegn = new Penguin("果果",10,20,"Q妹");
    //多态:1、方法重写是实现多态的基础 2、同一引用类型,使用不同的实例而执行不同操作
    master.cure(ppegn); //执行不同操作
    ppegn.print();
    }
    }

三、向上转型和向下转型

  1.向上转型:<父类型>    <引用变量名> = new   <子类型>();
  例如:int i = 3;
     double  a = i;  //自动进行类型转换
        double b = 3.14;
        int c = (int)b;  //强制进行类型转换

  • 将一个父类的引用指向一个子类对象成为向上转型
  • 此时通过父类引用调用的方法是子类覆盖或继承了父类的方法,而不是父类的方法
  • 此时通过父类引用变量无法直接调用子类特有的方法

  2.向下转型:<子类型>    <引用变量名> = (<子类型>)<父类型引用变量>;
   将一个指向子类对象的父类引用赋给一个子类的引用,即将父类类型转换为子类类型
     例如:Dog dog = (Dog)pet;   //将父类引用pet转换为Dog类型

四、instance运算符

 在向下转型的过程中,如果不是转换为真实子类类型,会出现转换异常,java中提供了instance运算符进行类型的判断

public void cure(Pet pe){
if(pe instanceof Dog){
//...
}else if(pe instanceof Penguin){
//.....
}
}

  注意:使用instance时,对象的类型必须和instance后面的参数所指定的类有继承关系,否则会出现编译错误

五、多态的应用

  • 可替换性:多态已存在的代码具有可替换性
  • 可扩充性:对代码具有可扩充性,增加新的子类不影响已存在类的多态性、继承性
  • 接口性:多态时父类想子类提供了一个共同接口,有子类来具体实现
  • 灵活性:多态在应用中体现了灵活多样的操作,提高了使用效率
  • 简化性:简化了引用软件的代码编写和修改过程,尤其是在处理大量对象的晕眩和操作时
  • 2中应用形式:
  1. 使用父类作为方法的形参
  2. 使用父类作为方法的返回值
    package com.abstractInterface;
    /*
    * 动物类
    * @author yutianbao
    * @param
    * @date 2019/3/20 13:32
    * @return
    * @Motto: good good study,day day up
    */
    public abstract class Animals { //抽象类
    //叫
    public abstract void cry();
    }
    /*
    * 狗狗类
    * @author yutianbao
    * @param
    * @date 2019/3/20 13:34
    * @return
    * @Motto: good good study,day day up
    */
    class Dog extends Animals{
    public void cry(){
    System.out.println("狗狗叫:汪汪汪");
    }
    }
    /*
    * 猫类
    * @author yutianbao
    * @param
    * @date 2019/3/20 13:37
    * @return
    * @Motto: good good study,day day up
    */
    class Cat extends Animals{
    public void cry(){
    System.out.println("猫叫:喵喵喵");
    }
    }
    /*
    * 鸭子类
    * @author yutianbao
    * @param
    * @date 2019/3/20 13:37
    * @return
    * @Motto: good good study,day day up
    */
    class Duck extends Animals{
    public void cry(){
    System.out.println("鸭子叫:嘎嘎嘎");
    }
    }

      

    package com.abstractInterface;
    /*
    * 主人类
    * @author yutianbao
    * @param
    * @date 2019/3/20 13:40
    * @return
    * @Motto: good good study,day day up
    */
    public class MasterPerson {
    //捐赠给别人动物
    public Animals domateAnimals(String type){
    Animals animals = null;
    if(type.equals("dog")){
    animals = new Dog();
    }else if(type.equals("cat")){
    animals = new Cat();
    }else if(type.equals("duck")){
    animals = new Duck();
    }
    return animals;
    }
    }

      

    package com.abstractInterface;
    /*
    * 测试类
    * @author yutianbao
    * @param
    * @date 2019/3/20 13:51
    * @return
    * @Motto: good good study,day day up
    */
    public class Test {
    public static void main(String[] args) {
    MasterPerson mPerson = new MasterPerson();
    Animals dog = mPerson.domateAnimals("dog");
    dog.cry();
    Animals cat = mPerson.domateAnimals("cat");
    cat.cry();
    Animals duck = mPerson.domateAnimals("duck");
    duck.cry();
    }
    }

    

Java面向对象 第4节 类的多态性的更多相关文章

  1. Java面向对象 第1节 类和对象

    一.Java 对象和类 面向对象语言三大特性:封装.继承.多态: 对象:描述客观事物的一个实体: 类:类是封装对象的属性和方法的载体,反过来说具有相同属性和行为的一类实体被称为类:类行为:方法:属性: ...

  2. Java面向对象 第3节 类的封装和继承

      一.封装 封装的概念:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的访问和操作. 封装的2个大致原则:1)把尽可能多的东西隐藏起来,对外提供便捷的接口 ...

  3. Java面向对象(一)类和对象

    面向过程和面向对象的区别 面向过程,强调的是功能行为,是将实现一个功能的步骤编写在一个函数中,以函数为最小单位. 面向对象,是将需要的功能封装进一个对象中,使一个对象具有很多的功能特征,以类/对象为最 ...

  4. java面向对象程序设计(下)-枚举类

    在某些情况下,一个类的对象是有限而且固定的,比如季节类,它只有4个对象;再比如行星类,目前只有8个对象,这些实例有限而且固定的类,在Java中被称为枚举类 JDK1.5新增了一个enum关键字,(它与 ...

  5. Java面向对象 第2节 Scanner 类和格式化输出printf

    §Scanner 类 java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入. 1.创建 Scanner 对象的基本语法:Scanner s = ...

  6. Java面向对象 第5节 抽象类和接口

    一.抽象类和抽象方法 区分抽象方法和普通方法1)当一个方法被abstract修饰时,该方法成为抽象方法2)抽象类所在的类必须定义为抽象类3)抽象方法不会有具体的实现,而是在抽象类的子类中通过方法重写进 ...

  7. java面向对象编程——第八章 类的高级概念

    8.1访问修饰符: public:该类或非该类均可访问: private: 只有该类可以访问: protected:该类及其子类的成员可以访问,同一个包中的类也可以访问: 默认:相同数据包中的类可以访 ...

  8. Java面向对象 第6节 异常

    一.认识异常 异常是指在程序运行过程中所发生的不正常事件,如文件找不到.网络连接不通或链接中断.算数运算出错.数组下标越界.装在一个不存在的类.对null对象操作.类型转换异常等.异常会中断正在运行的 ...

  9. java面向对象中的String类中12种常用的方法

    1.字符串与字符数组的转换 字符串可以使用toCharArray()方法变成一个字符数组,也可以使用String类的构造方法把一个字符数组变成一个字符串. public class StringAPI ...

随机推荐

  1. FLEX外包团队:Flex例子DEMO源码

    代码如下: <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx=& ...

  2. Java问题解决:The project cannot be built until build path errors are resolved

    参考:http://blog.csdn.net/marty_zhu/article/details/2566299 1,看看project -- Build Automatically有没有勾上?如果 ...

  3. loadrunner中web_reg_save_param和web_reg_save_param_ex的区别

    在使用Loadrunner进行性能测试,编写接口请求脚本时,通过会用到关联函数,而web_reg_save_param和web_reg_save_param_ex的函数有什么区别呢?以下为总结的两点, ...

  4. [HTML] HTML Lists

    无序列表: 1. unordered list 以<ul>开头,以</ul>结果. 每个list item 以<li> tag开头. 2. 样式: bullet(小 ...

  5. js的Timer方法

    如显示时间: <script> //获取时间 function mytime(){ var a = new Date(); var b = a.toLocaleTimeString(); ...

  6. mybatis_generator合并xml mapper文件

    一.问题 用的mybatis.generator 1.3.6版本,版本没啥大关系. 目前的xml输出有两个主要的问题: 1.xml追加而不是覆盖 这样就导致一个xml mapper文件每个node都重 ...

  7. 【C/C++】Rotate Array

    实现数组旋转(循环右移) 如数组 [1, 2, 3, 4, 5, 6, 7],右移 3 位则为 [5, 6, 7, 1, 2, 3, 4] 首先使用泛型函数 void Rotate(void *fro ...

  8. Vue.js 3.0 新特性预览

    总结起来,Vue 3 以下方面值得我们期待 : 更快 更小 更易于维护 更多的原生支持 更易于开发使用 完整的PPT:docs.google.com/presentatio… Evan 和 Vue 团 ...

  9. .net core webapi带权限的文件下载方法

    众所周知,在webapi中,如果有个接口需要权限,一般会将带权限的字段塞进header中.但是,在带权限的文档下载接口中,无论是用post,还是get方式,我们无法设置header头信息.苦恼呀?别急 ...

  10. 【转载】Oracle 中count(1) 、count(*) 和count(列名) 函数的区别

    1)count(1)与count(*)比较: 1.如果你的数据表没有主键,那么count(1)比count(*)快2.如果有主键的话,那主键(联合主键)作为count的条件也比count(*)要快3. ...