面向对象之多态
回顾
面向对象的特征:
1.继承:重用父类的内容,重用代码。满足 is-a 的关系就是继承,给多态做铺垫。
2.封装:隐藏内部细节,达到保护数据的行为。
3.多态:多种形态
在OOP中多态指对象的多种形式和能力
分类
1.静态多态:在编译期间,程序就能决定调用那个方法
2.动态多态:在程序运行期间,才能决定调用对象的那个方法
静态多态:方法的重载就体现了静态多态
在不同的环境下,相同的行为,不同的表现形式
public void eat(String message){
System.out.println("小黄正在吃:"+message);
}
public void eat(String place,String message){
System.out.println("小黄正在"+place+"吃:"+message);
}
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat("门口", "狗粮");
dog.eat("猪肉");
}
动态多态:在继承的环境下,父类对象引用指向子类对象(在操作时不知道具体子类的内容,父类给我们提供了行为,当代吗运行的时候决定执行哪一个行为,包括执行父类的行为还是子类的行为)
Wine wine = new JNC();
wine.drink();
Wine wine2 = new WLY();
wine2.drink();
Wine wine3 = new MT();
wine3.drink();
特点
1.父类对象可以将引用指向子类对象,也可以指向本类对象
2.多态其实指方法的多态:创建本类的对象调用就是本类的方法。创建子类的对象调用就是子类的方法。
3.如果子类没有重写父类的方法,默认调用子类继承的方法(父类的方法)
4.只能是父类对象指向子类对象。不能反过来 子类引用指向父类
静态多态和动态多态区别:
相同点:都是方法的多态,在代码执行过程中调用不同方法达到不同效果。
不同点:静态多态重载来实现的,动态多态是用重写来实现的。静态多态一个类的多个方法,相同行为不同表现形式
动态动态在运行的时候在决定执行的是某个子类里面的方法,将多态的方法分配到每个子类里面
对象的自动转型 向上转型
通过父类引用指向子类对象,其实子类自动转型成了父类的数据类型,在继承中重写了父类的方法,提供的方法比父类更加强大
public void eat(Wine wine){
Wine wine = new JNC();
wine.drink();
}
对象的强制类型转换 向下转型
向上转型存在一定的缺陷,将子类转换为父类对象,调用的时候只能调用父类的属性和行为,子类自己扩展的属性和行为无法使用。向下转型的好处,可以调用子类继承的属性和方法,还可以调用扩展的内容
public void eat(Wine wine){
wine.drink();
JNC jnc= (JNC) wine;
jnc.drinkType();//父类中没有drinkType方法,所以只能调用子类,必须进行强转。
}
instanceof
java的多态性到时引用变量类型和实际引用类型可以不一致,为了跟准确的区分出引用的是什么类型的对象,java引入了instanceof运算符
但是在java中不推荐使用它
public void eat(JNC jnc){ //通过重载来解决问题
jnc.drink();
jnc.drinkType();
}
public void eat(WLY wly){
System.out.println("不能喝");
}
public static void main(String[] args) {
Student2 s = new Student2();
JNC jnc = new JNC();
s.eat(jnc);
WLY wly = new WLY();
s.eat(wly);
}
多态存在三个条件:
1.要有继承 两个子类之间存在关系,子类要继承父类
2.要有重写 子类继承父类,子类一定重写父类的方法
3.父类引用指向子类对象
三个满足就符合多态特征
应用情况
1.动态绑定
Wine Wine = getObj(); //用父类接收不同的子类对象的方法和属性
public static Wine getObj(){
return new jnc();//可以设置不同的对象
}
2.多态参数
public void eat(Wine wine){ //可以将不同的对象参数传入
wine.drink();
JNC jnc= (JNC) wine;
jnc.drinkType();
}
equals()典型的多态表现 “abc”.equals(“abc”)现将括号里面的对象向上转型为Object,判断与“abc”的地址是否相等,相等返回true,否则对象向下转型为String,比较长度,在分别将数据保存在char[]数组中,依次进行比较,相等返回true
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
3.异构集合
在一个数组里面可以存放不同的对象,可以存子类对象,也可以存父类对象
Wine[] array = new Wine[3];//数组里存放的不同的子类
array[0]=jnc;
array[1]=mt;
array[2]=wly;