多态是指同一个方法调用,由于对象不同,可能会有不同的行为.
例子:
同样是调用人的”吃饭”的方法,张三是筷子吃,英国人是用叉子吃,印度人使用手吃
编译器类型指的是”=”左边的类型,运行时类型值得时”=’右边的类型.当有继承关系时,可能发生编译器类型和运行类型不同的情况,即编译类型是父类类型,运行类型是子类类型.即父类引用指向子类对象.
多态的要点:
多态是方法的多态,不是属性的多态(多态与属性无关)
多态存在的3个必要条件:继承,方法重写,父类引用指向子类对象
父类引用指向子类对象后.用该父类引用调用子类重写的方法,此使多态就出现了.
使用父类做方法的形参,是使用多态最多的场合,即使增加了新的子类,方法也无需改变,符合开闭原则.
父类引用做方法的形参,实参可以是任意子类对象,通过不同的子类对象实现不同的行为方式.另外即使增加了新的子类,方法也无需改变,提高了扩展性,符合开闭原则.
开闭原则
对扩展开放,对修改关闭
更通俗的讲,软件系统中各类组件,如模块(Moduels),类(Classes),以及功能(Functions)等,应该在不修改现有代码的基础上,引入新功能
这是面向对象设计需要遵守的最高原则也是最终目标.
多态向上转型
/** * 程序员 */ public class Programmer { public String name = "proName";//多态和成员变量无关 //子类继承的方法 public void writeCode() { System.out.println("=============Programmer writeCode======"); } //子类重写的方法 public void eat() { System.out.println("======Programmer eat====="); } }
/** * 中国程序员,继承的是程序员类 */ public class ChineseProgrammer extends Programmer { //继承的方法:writeCode() //重写的吃饭 public String name = "chName"; public void eat() { System.out.println("Chinese people eat rice by chopsticks"); } //特有的方法 public void playBoxing() { System.out.println("Chinese people play shadowBoxing every day");
/** * 英国程序员,继承程序员类 */ public class EnglishProgrammer extends Programmer { //继承的方法:writeCode() //重写的吃饭 public void eat() { System.out.println("England people eat meat by knife"); } //特有的方法 public void raceHorse() { System.out.println("England people like raceHorse"); } }
/** * 意大利程序员,继承程序员类 */ public class Italian extends Programmer{ //继承的方法:writeCode() //重写的吃饭 public void eat() { System.out.println("Chinese people eat pizza by hand"); } //特有的方法 public void playBoxing() { System.out.println("Italian people play football every day"); } }
/** * 食堂,使得所有程序员吃饭 */ public class Canteen { /* 使用父类做方法的形参 实参可以是任意子类对象!!!! */ public static void showEat(Programmer programmer) { programmer.eat(); } // public static void showEat(ChineseProgrammer programmer) { // programmer.eat(); // } // public static void showEat(EnglishProgrammer programmer) { // programmer.eat(); // } // public static void showEat(Italian programmer) { // programmer.eat(); // } public static void main(String[] args) { Programmer pro = new Programmer(); showEat(pro); ChineseProgrammer ch = new ChineseProgrammer();// 实参可以是任意子类对象 showEat(ch); EnglishProgrammer en = new EnglishProgrammer(); showEat(en); Italian it = new Italian(); showEat(it); EnglishProgrammer en1 = new EnglishProgrammer(); Programmer pro1 = en1; Programmer pro3 = new EnglishProgrammer();//多态 } }
在食堂类中显示程序员吃饭“showeat”方法中,形参是程序员类的方法
在调用 “showeat”方法,传入的实参可以是任意程序员的子类
多态向下转型
将父类的引用变量转换为子类类型,称为向下转型(downcasting),向下转型后就可以调用子类特有的方法
需要进行强制转换 Chinese ch=(Chinese)pro;
强制转换不是做手术,必须转换成真是子类型,否则ClassCastException;
向下转型之前肯定发生了向上转型
为了避免 ClassCastException ,向下转型之前使用instanceof先判断一下
Pro instanceof Italian
对象 instanceof 类或者接口
import com.sun.deploy.security.EnhancedJarVerifier;
import polymorphic.ChineseProgrammer;
import polymorphic.EnglishProgrammer;
import polymorphic.Italian;
import polymorphic.Programmer;
/*
instance 变量instance 类或者接口
*/
public class Testpoly {
public static void main(String[] args) {
//基本数据类型的类型转换
double d = 13.45;
int n;
n=(int )d;//强制转换 做手术
System.out.println(n);
//引用数据类型的强制转换
Programmer pro = new ChineseProgrammer();
pro.eat();
ChineseProgrammer ch = (ChineseProgrammer) pro;
ch.playBoxing();
//EnglishProgrammer en = (EnglishProgrammer) pro;//不能做手术,必须转换为真实的子类类型
//en.raceHorse();
if(pro instanceof ChineseProgrammer){
ChineseProgrammer ch2 = (ChineseProgrammer) pro;
ch2.playBoxing();
}
else if(pro instanceof EnglishProgrammer){
EnglishProgrammer en2 = (EnglishProgrammer) pro;
en2.raceHorse();
} else if (pro instanceof Italian) {
Italian it = (Italian) pro;
it.playBoxing();
}
System.out.println(pro instanceof Programmer);
System.out.println(pro instanceof ChineseProgrammer);
System.out.println(pro instanceof Object);
System.out.println(pro instanceof EnglishProgrammer);
}
}