一:多态的基本介绍
方法或者属性具有多种形态,是面向对象的第三大特征,多态是寄哪里在封装和继承基础之上的。
二:多态的具体体现
1:方法的多态
重写和重载就体现多态
package Data0801.Test0802;
/**
* 作者:sakura
* 日期:2022年08月02日 00:05
*/
public class test02 {
public static void main(String[] args) {
A a = new A();
a.sum(3,4);
a.sum(3,4,6);
B b = new B();
b.sum(2,4);
}
}
class A{
//重载
public double sum(int a, int b){
return a+b;
}
public double sum(int a, int b,int c){
return a+b+c;
}
}
class B extends A{
@Override
public double sum(int a, int b) {
System.out.println("方法重写完毕");
return super.sum(a, b);
}
}
2:对象的多态(重点,难点!!!)
:::danger
- 一个对象的编译类型和运行类型可以不一致
- 编译类型在定义对象是,就确定了,不能改变
- 运行类型是可以变化的
编译类型看定义是 = 好的左边,运行类型看 = 右边 :::
Animal animal = new Dog(); //编译类型是Animal,运行类型是Dog
animal = new cat(); //换了一个引用对象,运行类型变成了Cat
三:代码案例
1:多态基本体现
public class test03 {
public static void main(String[] args) {
//编译类型和运行类型
Animal animal = new Dog();
animal.cry();
Animal animal1 = new Cat();
animal1.cry();
}
}
public class Animal {
public void cry(){
System.out.println("动物在叫");
}
}
public class Cat extends Animal{
@Override
public void cry() {
System.out.println("猫在叫");
}
}
public class Dog extends Animal{
@Override
public void cry() {
System.out.println("狗在叫");
}
}
2:解决主人给动物喂食的问题
public class test04 {
public static void main(String[] args) {
Master sakura = new Master("sakura");
Animal animal = new Cat("L");
Food food = new fish("鱼");
sakura.feed(animal,food);
}
}
public class Master {
private String name;
public Master(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void feed(Animal animal , Food food){
System.out.println("主人:" + this.name + "给 " + animal.getName() + "喂食:" + food.getName());
}
}
public class Food {
private String name;
public Food(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class fish extends Food{
public fish(String name) {
super(name);
}
}
public class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Cat extends Animal{
public Cat(String name) {
super(name);
}
}
四:多态细节注意事项和细节讨论
-
1:多态的向上转型
本质:父类的引用指向子类的对象
- 语法:父类类型 引用名 = new 子类类型( );
- 特点:编译类型看左边,运行类型看右边
- 可以调用父类的所有成员
- 不能调用子类的特有成员
- 最终运行效果看子类的具体实现 ```java Animal animal = new cat(); Objectobj = new cat(); //Object 也是cat的父类
//向上转型调用方法的规则如下: //(1)可以调用父类中的所有成员(需遵守访问权限) //(2)但是不能调用子类的特有的成员 //(3)因为在编译阶段,能调用哪些成员,是由编译类型来决定的 //animal.catchMouse();错误 // //(4)最终运行效果看子类(运行类型)的具体实现, 即调用方法时,按照从子类(运行类型)开始查找方法 //,然后调用,规则我前面我们讲的方法调用规则一致。
animal.eat(); //如果想调用子类中的特有方法只能,向下转型
<a name="QlIMJ"></a>
#### 2:多态的向下转型
- **_语法:子类类型 __引用名 = (子类类型) 父类引用_**
- **_只能强转父类的引用,不能强转父类的对象_**
- **_要求父类的引用必须指向的时当前目标类型的对象_**
- **_当向下转型后,可以调用子类类型中的所有的成员_**
```java
Animal animal = new cat();
Cat cat = (Cat)animal;
3:属性的值没有重写之说看编译类型
public class PolyDetail02 {
public static void main(String[] args) {
//属性没有重写之说!属性的值看编译类型
Base base = new Sub();//向上转型
System.out.println(base.count);// ? 看编译类型 10
Sub sub = new Sub();
System.out.println(sub.count);//? 20
}
}
class Base {
//父类
int count = 10;//属性
}
class Sub extends Base {
//子类
int count = 20;//属性
}
五:instanceOF比较操作符
:::danger 用于判断对象的运行类型是否为XX类型或XX类型的子类型 :::
public class PolyDetail03 {
public static void main(String[] args) {
BB bb = new BB();
System.out.println(bb instanceof BB);// true
System.out.println(bb instanceof AA);// true
//aa 编译类型 AA, 运行类型是 BB //BB 是AA子类
AA aa = new BB();
System.out.println(aa instanceofAA); //true
System.out.println(aa instanceofBB); //true
Object obj = new Object();
System.out.println(obj instanceofAA);//false
String str = "hello";
//System.out.println(str instanceof AA); //fase
System.out.println(str instanceofObject);//true
}
}
六:Java动态绑定机制
- 当调用方法时,该方法会和该对象的内存地址/运行类型绑定
- 当调用对象的属性时,没有动态绑定机制,哪里调用哪里使用
public static void main(String[] args) {
A a = new B()
System.out.println(a.sum()); //40
System.out.println(a.sum(1); //30
}
class A {
public int i= 10;
public int sum() {
return getl()+ 10;
}
public int sum1(){
returni+ 10;
}
public int getl() {
return i;
}
}
class B extends A { // 子类
public int i = 20;
/*public int sum(){
return i+ 20;
}*/
public int getl() {
return i;
}
public int sum10 {
returni+ 10;
}
}