项目代码
https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter08/src/com/yinhai/poly_
目录
1.当调用对象方法的时候,该方法会和对象的内春地址/运行类型绑定
引出多态
编写一个程序 Master类中有一个feed方法,可以完成主人给动物喂食物的信息
public class Food {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Food(String name) {
this.name = name;
}
}
class Fish extends Food{
public Fish(String name) {
super(name);
}
}
class Bone extends Food{
public Bone(String name) {
super(name);
}
}
public class Animal {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Animal(String name) {
this.name = name;
}
}
class Cat extends Animal{
public Cat(String name) {
super(name);
}
}
class Dog extends Animal{
public Dog(String name) {
super(name);
}
}
public class Master {
private String name;
public Master(String name) {
this.name = name;
}
public void feed(Dog dog,Bone bone){
System.out.println("Master " + name + " feed " + dog.getName() + " " + bone.getName());
}
public void feed(Cat cat,Fish fish){
System.out.println("Master " + name + " feed " + cat.getName() + " " + fish.getName());
}
//.......当类变多时方法会变得很多
}
public class Poly01 {
public static void main(String[] args) {
Master master = new Master("Jack");
Dog dog = new Dog("xiaoYellow");
Bone bone = new Bone("gutou");
master.feed(dog,bone);
System.out.println(" ================== ");
Cat cat = new Cat("xiaoWeith");
Fish fish = new Fish("zayu");
master.feed(cat,fish);
}
}
引出一个问题,当后续对象变多的时候,feed方法会变得冗余,多次重载, 很麻烦,而且不利于代码维护
一、 多态的基本介绍
方法或者对象具有多种形态,是面向对象的第三大特征,多态是建立在封装和继承的基础之上的
1.方法的多态 重写和重载都能体现多态
package com.yinhai.poly_;
public class PloyMethod {
public static void main(String[] args) {
A a = new A();
a.sum(10,20);
a.sum(10,20,30);//The method overloading represents polymorphism
B b = new B();
a.say();
b.say(); //The method overriding represents polymorphism
}
}
class B{
public void say(){
System.out.println("This the Class B is used of method");
}
}
class A extends B {
public int sum(int n1,int n2){
return n1 + n2;
}
public int sum(int n1,int n2,int n3){
return n1 + n2 + n3;
}
public void say (){
System.out.println("This the Class A is used of method");
}
}
2.对象的多态(重要)
1)一个对象的变异类型和运行类型可以不一致
Animal animal = new Dog(); animal的变异类型是animal,运行类型是Dog
2)变异类型在定义对象时,就确定了,不能改变
3)运行类型是可以改变的
anmial = new Cat();
4)编译类型看定义时 = 号的左边,运行类型看 = 的右边
案例
package com.yinhai.poly_.polyobject;
public class PolyObject {
public static void main(String[] args) {
//The characteristics of object polymorphism
Animal animal = new Dog(); //The compile type is determined of Animal class
//But opera type is Dog of class
animal.cry();//because when run this line,system will find opera type of object,and its Dog of class
//so cry's method is Dog of class,system output "Dog crying...."
animal = new Cat(); //attention,right here that compil type still of Animal,but run type is change to Cat class
animal.cry();//now,system should be output "Cat crying..."
}
}
二、多态的快速入门
package com.yinhai.poly_.poly01;
public class Poly01 {
public static void main(String[] args) {
Master master = new Master("Jack");
Dog dog = new Dog("xiaoYellow");
Bone bone = new Bone("gutou");
master.feed(dog, bone);//run type is dog ,that can passing in Base class of Animal
//in other words,this is one way to used polymorphism,compil type not equal to run type
System.out.println(" ================== ");
Cat cat = new Cat("xiaoWeith");
Fish fish = new Fish("zayu");
master.feed(cat, fish);
}
}
public class Master {
private String name;
public Master(String name) {
this.name = name;
}
//now,can use polymorphism to solve that problem
public void feed(Animal animal,Food food){//compil type is Animal can point to object of Animal's subclasses
//compil type is Food can point to object of Food's subclasses
//can passing in all object of subclasses of compil type
System.out.println("Master " + name + " feed " + animal.getName() + " " + food.getName());
}
public void feed(Cat cat, Fish fish){
System.out.println("Master " + name + " feed " + cat.getName() + " " + fish.getName());
}
}
三、多态的细节和注意事项
1.多态存在的前提是两个对象存在继承关系
2.多态的向上转型(重要)
1)本质,父类的引用指向了子类的对象(有点像把子类提到父类)
public class PolyDetail {
public static void main(String[] args) {
//transition up; the reference to base class point to the object of subclasses
Animal cat = new Cat();
//Object obj = new Cat(); //can run? the answer is yes
}
}
2)语法:父类类型 引用名 = new 子类类型();
3)特点:变异类型看左边,运行类型看右边
可以调用父类中的所有成员(方法)(需遵守访问权限)
不能调用子类中的特有成员(方法);
因为在编译阶段能调用的成员是由编译类型来决定的
编译类型的父类里都没这个方法,当然会报错,但运行时就是看运行类型的子类里找
最终运行效果看子类的具体实现
即调用方法时,按照从子类开始查找方法
package com.yinhai.poly_.polydetail;
public class Animal {
String name = "animal";
int age = 10;
public void sleep(){
System.out.println("sleeping...");
}
public void run(){
System.out.println("running...");
}
public void eat(){
System.out.println("eating...");
}
public void show(){
System.out.println("Hello~");
}
}
public class Cat extends Animal{
public void eat(){//constitute override of method
System.out.println("Cat eating fish...");
}
public void catCatch(){
System.out.println("Catching mouse...");
}
}
public class PolyDetail {
public static void main(String[] args) {
//transition up; the reference to base class point to the object of subclasses
Animal cat = new Cat();
//Object obj = new Cat(); //can run? the answer is yes
//Object also base type of Cat
//cat.catCatch; this line was wrong
cat.eat();//eat method existence in cat class,so output "Cat eating..."
cat.run();//in cat class,system cant find method,
//so jump to Anmial class to find out eat method
cat.sleep();//Same as above
cat.show();//Same as above
}
}
3.多态的向下转型
1)语法:子类类型 引用名 = (子类类型)父类引用;
//transition down of polymorphism
//compilation type is Cat , run type also is Cat
Cat cat = (Cat) animal;
//Dog dog = (Dog) animal; // attention , a reference of base class must point to same object of subclasses
cat.catCatch();//so this line can passing in Cat class to output "Cat catch mouse"
2)只能强转父类的引用,不能强转父类的对象
3)要求父类的引用必须指向的是当前目标类型的对象
4)当向下转型后,就可以调用子类类型中的所有成员
4.属性没有重写一说,属性的值直接看编译类型
public class PolyDetail02 {
public static void main(String[] args) {
Base base = new Sub();
System.out.println();
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;
}
5.instanceOf比较操作符
用于判断对象的运行类型是否为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 = new AA();//compilation type is AA,run type is BB
System.out.println(aa instanceof AA);//true
System.out.println(aa instanceof BB);//false so this is run type judgement
Object o = new Object();
System.out.println(o instanceof AA);//false
}
}
class AA{
}
class BB extends AA{
}
四、多态的练习
1.
boolean b = (boolean)in错误 不是一个类型
Srtring str = (String)objPri错误 不是一个类型 指向Interger 的父类引用无法转成String
2.
五、动态绑定机制(重要)
package com.yinhai.poly_.dynamic_;
public class DynamicBinding {
public static void main(String[] args) {
A a = new B();
System.out.println(a.sum());//40 -->30
System.out.println(a.sum1());//30 --> 20
}
}
class A {
public int i = 10;
public int sum(){//run this statement
return getI() + 10;//and run getI , so here is a question ,where is run to? is A or B?
//so elicitation dynamic binding
//mechanism of dynamic binding
//1.when running object method,this object method will bind to run type
//so getI will use method of class B
//output 30
//2.when running parameter of object,have not dynamic binding! in other way , where declaration where used
}
public int sum1(){
return i + 10;//so run this line,here is will return i,this parameter is class A,have not dynamic binding!
}
public int getI(){
return i;
}
}
class B extends A{
public int i = 20;
// public int sum(){
// return getI() + 10; //to find class A of sum method ,if be annotated with this statement
// }
// public int sum1(){
// return i + 10; //to find sum method of class A ,if be annotated with this statement
// }
public int getI(){
return i; //not dynamic binding
}
}
1.当调用对象方法的时候,该方法会和对象的内春地址/运行类型绑定
2.当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
六、 多态的应用
1.多态数组
package com.yinhai.poly_.polyarr_;
public class PloyArray {
public static void main(String[] args) {
Person[] persons = new Person[5];//dynamic array
persons[0] = new Person("JACK",20);
persons[1] = new Student("xiaoming",18,60);
persons[2] = new Student("xiaohuang",20,99);
persons[3] = new Teacher("Mr.huang",26,9000);
persons[4] = new Teacher("Ms.wang",26,7000);
//iterate over array to running 'say' method
for(int i = 0;i < persons.length;i++){
//compilation type of person[i] is fixed,but run type is dynamic
System.out.println(persons[i].say());
if(persons[i] instanceof Student){//to use for unique method of subclass
//use the instanceof statement to determine if this is the same type or subclasses
Student student = (Student) persons[i];
student.study();//transition down to use method of subclasses
//((Student) persons[i]).study();
// can also use this statement ,that also can output the study method
} else if(persons[i] instanceof Teacher){
//same above if statement
Teacher teacher = (Teacher) persons[i];
teacher.teach();//same above
//((Teacher) persons[i]).teach();//same above
}else if (persons[i] instanceof Person){
}
else{
System.out.println("Have one data is neither student " +
"nor teacher,please check correctness of the data ");
}
}
}
}
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String say(){
return name + " " + age;
}
}
public class Student extends Person{
private double score;
public Student(String name, int age,int score) {
super(name, age);
this.score = score;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public String say() {
return super.say() + " score=" + score;
}
public void study(){
System.out.println(super.getName() + " studying...");
}
}
public class Teacher extends Person{
private double salary;
public Teacher(String name, int age, double salary) {
super(name, age);
this.salary = salary;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String say() {
return super.say() + " salary=" + salary;
}
public void teach(){
System.out.println(super.getName() + " teaching...");
}
}
2.多态参数
public class PolyParameter {
public static void main(String[] args) {
Employee boss = new Manger("boss",20000,120000);
Employee xiaowang = new OrdinaryStaff("xiaowang", 2000);
A a = new A();
a.showEmpAnnal(boss);
a.showEmpAnnal(xiaowang);
a.testWork(boss);
a.testWork(xiaowang);
}
}
class A{
public void showEmpAnnal(Employee e){
System.out.println(e.getName() + " " + e.getAnnual()) ;
}
public void testWork(Employee e){
if(e instanceof Manger){
((Manger) e).manage();
}else if (e instanceof OrdinaryStaff){
((OrdinaryStaff) e).work();
}
}
}
public class Employee {
private String name;
private int salary;
public int getAnnual(){
return salary * 12;
}
public Employee(String name, int salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
public class Manger extends Employee{
private int bones;
public int getAnnual(){
return super.getAnnual();
}
public Manger(String name, int salary,int bones) {
super(name, salary);
this.bones = bones;
}
public void manage(){
System.out.println(getName() + " managing...");
}
public int getBones() {
return bones;
}
public void setBones(int bones) {
this.bones = bones;
}
}
public class OrdinaryStaff extends Employee{
public void work(){
System.out.println(getName() + " working...");
}
public int getAnnual(){
return super.getAnnual();
}
public OrdinaryStaff(String name, int salary) {
super(name, salary);
}
}