多态
多态即 多种 状态
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的
方法的多态
class Test {
public static void main(String[] args) {
//方法重载体现多态
A a = new A();
//这里我们传入不同的参数,就会调用不同sum方法,就体现多态
System.out.println(a.sum(10, 20));
System.out.println(a.sum(10, 20, 30));
//方法重写体现多态
B b = new B();
a.say();
b.say();
}
}
class B { //父类
public void say() {
System.out.println("B say() 方法被调用...");
}
}
class A extends B {//子类
public int sum(int n1, int n2){//和下面sum 构成重载
return n1 + n2;
}
public int sum(int n1, int n2, int n3){
return n1 + n2 + n3;
}
public void say() {
System.out.println("A say() 方法被调用...");
}
}
对象的多态(核心)
重要的话: (介绍) 多态在继承和封装的基础之上
-
一个对象的编译类型和运行类型可以不一致
//Animal animal=new Dog(); //不一致 //animal的编译类型是Animal,运行类型是 Dog, new Dog()才是对象 animal是对象名字 //Animal animal=new Animal(); //一致 //animal =new Cat(); //Animal是编译类型,而Cat是运行类型
-
编译类型在定义对象时,就确定了,不能改变
public class PolyObject { public static void main(String[] args) { //体验对象多态特点 //animal 编译类型就是 Animal , 运行类型 Dog Animal animal = new Dog();//定义声明对象 //因为运行时 , 执行到改行时,animal运行类型是Dog,所以cry就是Dog的cry animal.cry(); //小狗汪汪叫 //animal 编译类型 Animal,运行类型就是 Cat animal = new Cat(); animal.cry(); //小猫喵喵叫 } }
-
运行类型是可以改变的
-
编译类型看定义时=号的左边,运行类型看=号右边
主人喂养 动物食物例子(快速入门)
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(Dog dog, Bone bone) {
// System.out.println("主人 " + name + " 给 " + dog.getName() + " 吃 " + bone.getName());
// }
//使用多态机制,可以统一的管理主人喂食的问题
//animal 编译类型是Animal,可以指向(接收) Animal子类的对象
//food 编译类型是Food ,可以指向(接收) Food子类的对象
//多态
public void feed(Animal animal,Food food){
System.out.println(name+"喂给"+animal.getName()+""+food.getName());
}
}
public class Animal {//动物类
private String name;
public Animal(String name){
this.name=name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class Dog extends Animal{//狗类
public Dog(String name){
super(name);
}
}
public class Food { //食物类
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Food(String name){
this.name=name;
}
}
public class Bone extends Food {//骨头类
public Bone(String name) {
super(name);
}
}
public class Test {//测试代码
public static void main(String[] args) {
Dog dog=new Dog("大黄");
Master master=new Master("李华");
Bone bone =new Bone("大骨头");
//master.feed(dog,bone);
Animal animal =new Dog("小白");
Food food =new Bone("小骨头");
master.feed(dog,bone); //多态
}
}
多态的注意事项和细节
多态的基础是两个对象(类)存在继承关系
1.向上转型
-
本质:父类的引用指向了子类的对象
-
语法: 父类类型 引用名=new 子类类型( );
//Animal animal =new Dog("小白"); //animal是引用名 Dog是子类类型
-
特点:
(1)可以调用父类中的所有成员(需遵守访问权限)
(2)但是不能调用子类的特有的成员//例子 public class Animal { String name = "动物"; int age = 10; public void sleep(){ System.out.println("睡"); } public void run(){ System.out.println("跑"); } public void eat(){ System.out.println("吃"); } public void show(){ System.out.println("hello,你好"); } } public class Cat extends Animal { public void eat(){//方法重写 System.out.println("猫吃鱼"); } public void catchMouse(){//Cat特有方法 System.out.println("猫抓老鼠"); } } public class Test { public static void main(String[] args) { //向上转型: 父类的引用指向了子类的对象 //语法:父类类型引用名 = new 子类类型(); Animal animal = new Cat(); Object obj = new Cat();//可以吗? 可以 Object 也是 Cat的父类,间接父类也是父类 //向上转型调用方法的规则如下: //(1)可以调用父类中的所有成员(需遵守访问权限) //(2)但是不能调用子类的特有的成员 //animal.catchMouse();错误 //(#)因为在编译阶段,能调用哪些成员,是由编译类型来决定的 //(4)最终运行效果看子类(运行类型)的具体实现, 即调用方法时,按照从子类(运行类型)开始查找方法 //,然后调用,规则我前面我们讲的方法调用规则一致。 animal.eat();//猫吃鱼.. animal.run();//跑 animal.show();//hello,你好 animal.sleep();//睡 } }
2.向下转型
- 语法:子类类型 引用名 = (子类类型) 父类引用;
- 只能强转父类的引用,不能强转父类的对象
- 要求父类的引用必须指向的是当前目标类型的对象
- 当向下转型后,可以调用子类类型中所有得成员
//(1)语法:子类类型 引用名 =(子类类型)父类引用;
//问一个问题? cat 的编译类型 Cat,运行类型是 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 关键字
package com.hspedu.poly_.detail_;
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 instanceof AA);
System.out.println(aa instanceof BB);
Object obj = new Object();
System.out.println(obj instanceof AA);//false
String str = "hello";
//System.out.println(str instanceof AA);
System.out.println(str instanceof Object);//true
}
}
class AA {} //父类
class BB extends AA {}//子类