在上海乐字节学习Java的第十五天

CodeNebula
• 阅读 115

Java多态(上)

多态意味着允许不同类的对象对同一消息做出不同的响应

编译时多态(设计时多态,一般为方法重载)

运行时多态(程序运行时动态决定调用哪个方法)

必要条件:
满足继承关系
父类引用指向子类对象
从一定角度来看,封装和继承几乎都是为多态准备的
现实中,多态的例子数不胜数
动物们都有吃东西、跑、跳、叫的方法,不同的动物表现方式不同

类型转换向上转型(Upcast):将子类型转换为父类型
隐式/自动类型转换,是小类型到大类型的转换
对于向上的类型转换,不需要显示指定,即不需要加上前面的小括号和父类类型名
向下转型(Downcast):将父类型转换为子类型
将一个指向子类对象的父类引用赋值给一个子类的引用
强制类型转换,是大类型到小类型
父类型的引用必须指向转型的子类的对象,即指向谁才能转换谁。不然也会编译出错
通过instanceof运算符,来解决引用对象的类型,避免类型转换的安全性问题,提高代码的强壮性

注意
父类引用指向子类实例时,可以调用子类重写父类的方法以及直接继承父类的方法,无法调用子类的特有的方法
静态static方法属于特殊情况,静态方法只能继承,不能重写。调用的时候用谁的引用,则调用谁的版本
代码实现

Animal类

package com.SH.animal;

//抽象类:不允许实例化,可以通过向上转型,指向子类实例
public abstract class Animal {
    //属性:昵称、年龄
    private String name;
    private int month;
    
    public Animal(){
        
    }
    
    public Animal(String name,int month){
        this.name=name;
        this.month=month;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        this.month = month;
    }
    
    //方法:吃东西
    //抽象方法:不允许包含方法体;子类中需要重写父类的抽象方法,否则,子类也是抽象类
    //static final private不能与abstract并存
    public abstract void eat();
    
    public static void say(){
        System.out.println("动物间打招呼");
    }
}

Cat类


package com.SH.animal;

public class Cat extends Animal {
    //属性:体重
    private double weight;
    
    public Cat(){
        
    }
    
    public Cat(String name,int month,double weight){
        super(name,month);
//        this.setMonth(month);
        this.weight=weight;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }
    
    
    //方法:跑动
    public void run(){
        System.out.println("小猫快乐的奔跑");
    }
    
    
    //方法:吃东西(重写父类方法)
    @Override
    public void eat() {
        System.out.println("猫吃鱼~~");
    }
    
    public static void say(){
        System.out.println("小猫碰胡须");
    }

    public void playBall() {
        // TODO Auto-generated method stub
        System.out.println("小猫喜欢玩线球");
    }

Dog类

package com.SH.animal;

public class Dog extends Animal{
    //属性:性别
    private String sex;
    
    public Dog(){
        
    }
    
    public Dog(String name,int month,String sex){
        this.setMonth(month);
        this.setName(name);
        this.setSex(sex);
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
    
    
    //方法:睡觉
    public void sleep(){
        System.out.println("小狗有午睡的习惯");
    }
    
    
    //方法:吃东西(重写父类方法)
    @Override
    public void eat() {
        System.out.println("狗吃肉~~");
        
    }
}

Test类


package com.SH.test;

import com.SH.animal.Animal;
import com.SH.animal.Cat;
import com.SH.animal.Dog;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
//        Animal one=new Animal();//1

向上转型、隐式转型、自动转型
父类引用指向子类实例,可以调用子类重写父类的方法以及父类派生的方法,无法调用子类独有方法

注意:父类中的静态方法无法被子类重写,所以向上转型之后,只能调用到父类原有的静态方法
小类转型为大类

        */
        Animal two=new Cat();//2
        two.say();
        Cat cat=(Cat)two;
        cat.say();

        Cat cat=new Cat();
        two=cat;
        Animal three=new Dog();//3
        
        one.eat();
        two.eat();
        two.setMonth(2);
        two.getMonth();
        two.run();
        three.eat();
        System.out.println("=================");
        /*向下转型、强制类型转换
         * 子类引用指向父类对象,此处必须进行强转,可以调用子类特有的方法
         * 必须满足转型条件才能进行强转
         * instanceof运算符:返回true/false
         */
    if(two instanceof Cat){
            Cat temp=(Cat)two;
            temp.eat();
            temp.run();
            temp.getMonth();
            System.out.println("two可以转换为Cat类型");
        }
    
        if(two instanceof Dog){
            Dog temp2=(Dog)two;
            temp2.eat();
        temp2.sleep();
            temp2.getSex();
            System.out.println("two可以转换为Dog类型");
    }

        if(two instanceof Animal){
            System.out.println("Animal");
        }
    
        if(two instanceof Object){
            System.out.println("Object");
    }
        

类型转换案例
Master类


package com.SH.animal;

public class Master {
喂宠物
喂猫咪:吃完东西后,主人会带着去玩线球
喂狗狗:吃完东西后,主人会带着狗狗去睡觉
养兔子、养鹦鹉、养乌龟

方案1:编写方法,传入不同类型的动物,调用各自的方法

public void feed(Cat cat){
cat.eat();
cat.playBall();
public void feed(Dog dog){
dog.eat();
dog.sleep();

方案2:编写方法传入动物的父类,方法中通过类型转换,调用指定子类的方法

public void feed(Animal obj){
obj.eat();
if(obj instanceof Cat){
Cat temp=(Cat)obj;
temp.playBall();
}else if(obj instanceof Dog){
Dog temp=(Dog)obj;
temp.sleep();
}

    

饲养何种宠物
空闲时间多:养狗狗

空闲时间不多:养猫咪

方案1:

public Dog hasManyTime(){
System.out.println("主人休闲时间比较充足,适合养狗狗");
return new Dog();
public Cat hasLittleTime(){
System.out.println("主人平时比较忙碌,适合养猫咪");
return new Cat();

方案2:

public Animal raise(boolean isManyTime){
if(isManyTime){
System.out.println("主人休闲时间比较充足,适合养狗狗");
return new Dog();
}else{
System.out.println("主人平时比较忙碌,适合养猫咪");
return new Cat();
}

MasterTest类

package com.SH.test;
import com.SH.animal.Animal;
import com.SH.animal.Cat;
import com.SH.animal.Dog;
import com.SH.animal.Master;
public class MasterTest {
public static void main(String[] args) {
Master master=new Master();
Cat one=new Cat();
Dog two=new Dog();
master.feed(one);
master.feed(two);
System.out.println("=============");
boolean isManyTime=false;
Animal temp=master.raise(isManyTime);
if(isManyTime){
temp=master.hasManyTime();
}else{
temp=master.hasLittleTime();
System.out.println(temp);
}

抽象类&抽象方法
应用场景:
某个父类只是知道其他子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法

abstract定义抽象类
抽象类不能直接实例化,只能被继承,可以通过向上转型完成对象实例
abstract定义抽象方法,不需要具体实现
包含抽象方法的类是抽象类
抽象类中可以没有抽象方法
子类如果没有重写父类所以抽象方法,则也要定义为抽象类
abstract不能与 static、final、private共存
抽象方法在子类实现时访问权限必须大于等于父类方法

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
4年前
java面试(1)
1.面向对象的基本特征  封装、继承、多态、  封装:把客观事物封装成类  继承:继承一个类,就可以使用这个类的所有功能,并且在无需编写原来类的情况下对这些功能进行扩展  多态:子对象调用父对象,父对象会根据当前调用的子对象以不同的方式运作  实现多态:覆盖,重载2.final\\finally\\finalize的区别  fin
Wesley13 Wesley13
4年前
java中多态的实现机制
多态的概念:  简单来说就是事物在运行过程中存在的不同状态,即父类或接口定义的引用变量指向子类或具体实现类的实例对象。程序调用方法在运行期才进行动态绑定,而不是引用变量的类型中定义的方法。多态存在的前提:1、存在继承关系,子类继承父类;2、子类重写父类的方法;3、父类引用指向子类对象。具体实例:1、定义一个父类:Animal
Wesley13 Wesley13
4年前
java面向对象的三大特性
java面向对象的三大特性1.封装,把事物封装成抽象的类,通过访问控制符把自己的成员变量和函数对不可信的进行信息隐藏以及提供方法给可信的类和对象来操作。2.继承,继承可以使用现有类的所有功能和成员变量,并且无需重新编写原来的类的情况下对这些功能进行扩展。3.多态,实现了对代码的复用,多态具体体现为重载和重
小万哥 小万哥
2年前
C++虚函数详解:多态性实现原理及其在面向对象编程中的应用
在面向对象的编程中,多态性是一个非常重要的概念。多态性意味着在不同的上下文中使用同一对象时,可以产生不同的行为。C是一种面向对象的编程语言,在C中,虚函数是实现多态性的关键什么是虚函数虚函数是一个在基类中声明的函数,它可以被子类重写并提供不同的实现
待兔 待兔
5年前
Java多态实现原理
Java多态概述多态是面向对象编程语言的重要特性,它允许基类的指针或引用指向派生类的对象,而在具体访问时实现方法的动态绑定。Java对于方法调用动态绑定的实现主要依赖于方法表,但通过类引用调用(invokevirtual)和接口引用调用(invokeinterface)的实现则有所不同。类引用调用的大致过程为:Java编译器将Java源代码编译成c
Wesley13 Wesley13
4年前
C++课程第五次博客——多态
\TOC\多态性Part1多态性概述多态是指同样的消息被不同类型的对象接收时导致不同的行为。在C中,所谓信息是指对类的成员函数的调用,不同的行为是指不同的实现,也就是调用了不同的函数。1)多态的类型分为四类:重载多态,强制多态,包含多态和参数多态。前两者为专用多态,而后者称为通用多态。2)
Wesley13 Wesley13
4年前
C++多态性总结
一,C多态性概述多态是指同样的消息被不同类型的对象接受时导致不同的行为。所谓消息是指对类的成员函数的调用,不同的行为是指不同的实现,也就调用不同的函数。换言之,多态指的就是用同样的接口访问功能不同的函数,从而实现“一个接口,多种方法”。二,多态性分类!在这里插入图片描述(https://osc
Stella981 Stella981
4年前
Socket与系统调用深度分析
Socket与系统调用深度分析实验环境:Linux5.0.1内核32位系统的MenuOS本文主要解决两个问题用户态如何通过中断进入socket的系统调用socket抽象层如何通过多态的机制,来支持不同的传输层的协议。也就是socket作为父类,TCP/UDP为子类,父类指向子类对象,实现多态
Wesley13 Wesley13
4年前
JAVA面向对象
一、java面向对象的特征?答:java面向对象的特征:封装、继承、多态、抽象。如果问java面向对象的三大特征是什么?那就是封装、继承、多态,但说到面向对象,还有一个很主要的特征就是抽象。1、封装a)铺垫:Java把真实世界中某些具有共同特征的实体抽象成Java中的类,类的实例就是一个对象,而对象和真实世界的实体是一一
Wesley13 Wesley13
4年前
C++多态性与虚函数
  派生一个类的原因并非总是为了继承或是添加新的成员,有时是为了重新定义基类的成员,使得基类成员“获得新生”。面向对象的程序设计真正的力量不仅仅是继承,而且还在于允许派生类对象像基类对象一样处理,其核心机制就是多态和动态联编。(一)多态性  多态是指同样的消息被不同的对象接收时导致不同的行为。所谓消息是指对类成员函数的调用,不同的行为是指的不同的实现
小万哥 小万哥
1年前
深入理解 C++ 中的多态与文件操作
C多态多态(Polymorphism)是面向对象编程(OOP)的核心概念之一,它允许对象在相同操作下表现出不同的行为。在C中,多态通常通过继承和虚函数来实现。理解多态想象一个场景,你有一个动物园,里面有各种动物,如猫、狗、鸟等。每个动物都有自己的叫