一、多态的概念

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

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

二、实现多态

  多态(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. linux 新建用户、用户组 以及为新用户分配权限的基本操作

    分享下Linux系统中创建用户.设置密码.修改用户.删除用户的命令: 创建用户:useradd testuser  创建用户testuser设置密码:passwd testuser  给已创建的用户t ...

  2. .gitlab-ci.yml简介

    关键字   script 由Runner执行的Shell脚本. image 使用docker镜像,  image:name service 使用docker  services镜像, services ...

  3. Axure 页面内多组内容切换的实现 + 利用一个内联框架实现百度地图访问

    Axure  页面内多组内容切换的实现,场景:点击某个元件的时候,会显示响应的页面 操作:将显示的页面设置为动态面板,如图所示应该设置动态面板的状态为三个状态,分别为点击qq账号.手机账号.邮箱账号时 ...

  4. php格式化json字符串

    header('content-type:application/json;charset=utf8'); $arr = array( 'status' => true, 'errMsg' =& ...

  5. [Spring MVC] 表单提交日期转换问题,比如可能导致封装实体类时400错误

    三种格式的InitBinder @InitBinder//https://stackoverflow.com/questions/20616319/the-request-sent-by-the-cl ...

  6. net基础语法

    一.net基础语法流程图

  7. 在 .NET项目中使用 Redis(2018.10.16)

    1. 打开NuGet管理器搜索redis,安装:“StackExchange.Redis” 2. 配置 Web.config 文件 <connectionStrings> <add ...

  8. [luogu P3369]【模板】普通平衡树(Treap/SBT)

    [luogu P3369][模板]普通平衡树(Treap/SBT) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除x数(若有多个相同的数,因只删 ...

  9. MapServer Tutorial——MapServer7.2.1教程学习——第一节用例实践:Example 1.4 Labeling the Map

    MapServer Tutorial——MapServer7.2.1教程学习——第一节用例实践:Example 1.4 Labeling the Map 一.前言 MapServer拥有非常灵活的标签 ...

  10. 跟随我在oracle学习php(1)

    所有的web页面都由HTML(超文本标记语言)构成,每种浏览器都将代码转换成我们所看到的页面. 这是基本上是每个程序员写的第一个代码“hello world” 这是浏览器翻译后的结果 首先<&g ...