面向对象程序三大特性一:多态(超详细)

目录

1.重写

1.1基本语法规则

1.2规则深化

1.3重写与重载的区别

2.向上转型

2.1简单介绍

2.3向上转型的作用

3.向下转型

3.1介绍

[3.2instanceof 基本介绍](#3.2instanceof 基本介绍)

4.多态

4.1多态实现条件

4.2避免在构造方法中调用重写的方法


1.重写

重写 (override) :也称为覆盖。重写是子类对父类非静态、非 private 修饰,非 final 修饰,非构造方法等的实现过程 进行重新编写, 返回值和形参都不能改变即外壳不变,核心重写。

1.1基本语法规则

(++1)++ ++返回值类型 (2)方法名 (3)参数列表 要完全一致++
例子:

将eat()方法在子类中进行重写

1.2规则深化

(1) 被重写的方法返回值类型可以不同 , ++但是必须是具有父子关系的++
(2) ++访问权限不能比父类中被重写的方法的访问权限更低++ 。例如:如果父类方法被 public 修饰,则子类中重写该方 法就不能声明为 protected
(3) ++父类被static、final和private修饰的方法、构造方法都不能被重写。++

1.3重写与重载的区别

重写和重载就体现多态

静态绑定:也称为前期绑定(早绑定),++即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。++典型代 表函数重载。
动态绑定 :也称为后期绑定 ( 晚绑定 ) ,++即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体 调用那个类的方法。++
动态绑定的图解:(图1-1)

(图1-1)


2.向上转型

2.1简单介绍

向上转型:
实际就是创建一个子类对象,将其当成父类对象来使用
语法格式:
父类类型 对象名 = new 子类类型()

具体代码在代码(2-1)

向上转型的形式

(1)直接赋值

Animal animal = new Cat("元宝",2);

(2)方法传参

++就是传参时进行 向上转型++

(3)方法返回

同理:++就是返回时进行 向上转型++

2.3向上转型的作用

我们按向上转型 的语法写完代码具体能做些什么?

(1)调用父类特有的方法

(2)仅调用被子类重写的方法
看代码(2-1)

java 复制代码
public class Animal {
    String name;
    int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void eat(){
        System.out.println(name+"吃点啥");
    }
    public void Father(){
        System.out.println("我是父类");
    }
}
java 复制代码
public class Dog extends Animal{

    public Dog(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println(name+"吃狗粮");
    }

    public void cry(){
        System.out.println("狗叫");
    }
}
java 复制代码
public class Cat extends Animal{
    public Cat(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println(name+"吃猫粮");
    }
    public void cry(){
        System.out.println("猫叫");
    }
}
java 复制代码
public class Text {
    public static void fun(Animal a){
        a.eat();
    }

    public static void main(String[] args) {
      Animal animal1=new Dog("圆圆",19);
      Animal animal2=new Cat("方方",17);
      animal1.Father();
      fun(animal1);
      fun(animal2);
    }
}

运行结果:

(1)调用父类特有的方法

无法调用子类特有方法

(2)仅调用被子类重写的方法

问:如果想调用子类特有方法,怎么办?


3.向下转型

3.1介绍

将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的 方法,此时:将父类引用再还原为子类对象即可,即向下转换。
++Animal,Dog的代码请看代码(2-1)++

java 复制代码
class Text2{
    public static void main(String[] args) {
        Animal a1=new Dog("haha",8);
        if(a1 instanceof Dog){
            Dog dog=(Dog) a1;
            dog.cry();
        }
    }
}

运行结果:

3.2instanceof 基本介绍

语法为:

引用类型变量(object) instanceof 类(class)

功能:

判断前面的对象是否属于后面的类,或者属于其子类;

如果是,返回 true ,不是返回 false

instanceof 前面的引用变量编译时的类型要么与后面的类型相同,要么与后面的类型具有父子继承关系


4.多态

4.1****多态实现条件

  1. 必须在继承体系下
    2 . 子类必须要对父类中方法进行重写
    3 . 通过父类的引用调用重写的方法
    缺一不可(上面 ++代码(2-1)++ 其实已经使用了 多态
    多态体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法
    我们再看一个新例子
    例子:
java 复制代码
public class Shape {
    public void draw(){
        System.out.println("图形");
    }

}
class Rect extends Shape{
    @Override
    public void draw() {
        System.out.println("矩形");
    }
}

class Cycle extends Shape{
    @Override
    public void draw() {
        System.out.println("圆");
    }
}

class Flower extends Shape{
    @Override
    public void draw() {
        System.out.println("花");
    }
}
class Text2{
    public static void main(String[] args) {
        Shape shape[]={new Cycle(),new Rect(),new Flower()};
        for(Shape shape1:shape){
            shape1.draw();
        }
    }
}

运行结果:


多态缺陷:

  1. 属性没有多态性
    当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性
  2. 构造方法没有多态性

4.2避免在构造方法中调用重写的方法

我们创建两个类 , B 是父类 , D 是子类 . D 中重写 func 方法 . 并且在 B 的构造方法中调用 func

java 复制代码
class B {
public B() {
// do nothing
func();
}
public void func() {
System.out.println("B.func()");
}
}
class D extends B {
private int num = 1;
@Override
public void func() {
System.out.println("D.func() " + num);
}
}
public class Test {
public static void main(String[] args) {
D d = new D();
}
}

执行结果
D . func () 0
解释:

(1) 构造 D 对象的同时 , 会调用 B 的构造方法
(2)B 的构造方法中调用了 func 方法 , 此时会触发动态绑定 , 会调用到 D 中的 func
(3) 此时 D 对象自身还没有构造 , 此时 num 处在未初始化的状态 , 值为 0
结论 : " 用尽量简单的方式使对象进入可工作状态 ", 尽量不要在构造器中调用方法 ( 如果这个方法被子类重写 , 就会触 发动态绑定, 但是此时子类对象还没构造完成 ), 可能会出现一些隐藏的但是又极难发现的问题


以上为我个人的小分享,如有问题,欢迎讨论!!!

都看到这了,不如关注一下,给个免费的赞

相关推荐
上等猿1 分钟前
集合stream
java
java1234_小锋5 分钟前
MyBatis如何处理延迟加载?
java·开发语言
菠萝咕噜肉i6 分钟前
MyBatis是什么?为什么有全自动ORM框架还是MyBatis比较受欢迎?
java·mybatis·框架·半自动
林的快手21 分钟前
209.长度最小的子数组
java·数据结构·数据库·python·算法·leetcode
FeboReigns23 分钟前
C++简明教程(10)(初识类)
c语言·开发语言·c++
学前端的小朱24 分钟前
处理字体图标、js、html及其他资源
开发语言·javascript·webpack·html·打包工具
向阳12181 小时前
mybatis 缓存
java·缓存·mybatis
上等猿1 小时前
函数式编程&Lambda表达式
java
摇光931 小时前
js高阶-async与事件循环
开发语言·javascript·事件循环·宏任务·微任务
沐泽Mu1 小时前
嵌入式学习-QT-Day09
开发语言·qt·学习