多态
多态指的是同一个方法调用,由于对象不同可能会有不同的行为。现实生活中,同一个方法,具体实现会完全不同。 比如:同样是调用人的“休息”方法,张三是睡觉,李四是旅游,高淇老师是敲代码,数学教授是做数学题; 同样是调用人“吃饭”的方法,中国人用筷子吃饭,英国人用刀叉吃饭,印度人用手吃饭。
多态的要点:
- 多态是方法的多态,不是属性的多态(多态与属性无关)。
- 多态的存在要有3个必要条件:继承,方法重写,父类引用指向子类对象。
- 父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。
package Chapter_5;
/**
* 测试多态
* @author 与猫子
*
*/
public class TestPolymorphism {
public static void main(String[] args) {
Animal a = new Animal();
animalShout(a);
Dog dog =new Dog();
animalShout(dog);//这里传递的是dog,是Dog的对象,
//Dog是Animal的子类
//dog传递给animalShout(Animal a)方法的父类引用(指Animal a)
//所以父类引用(Animal a)指向子类对象(dog),
//父类引用调用了子类重写的方法,此时多态出现
animalShout(new Cat());
}
static void animalShout(Animal a) {
a.shout();
}
//如果没有多态就需要多编写很多方法,如下,会出现大量重载的方法,代码臃肿
// static void animalShout(Dog dog) {
// dog.shout();
// }
//
// static void animalShout(Cat cat) {
// cat.shout();
// }
}
class Animal{
public void shout() {
System.out.println("叫了一声!");
}
}
class Dog extends Animal{//继承
public void shout() {//方法的多态
System.out.println("汪汪汪!");
}
}
class Cat extends Animal{//继承
public void shout() {//方法的多态,指重写
System.out.println("喵喵喵!");
}
}
对象的转型
对象的转型分为向上转型和向下转型
对象的上转型对象
父类引用指向子类对象,这个过程为向上转型,属于自动类型转换。
- 上转型对象不能操作子类的新增的成员变量/方法
- 上转型对象可以访问子类继承或隐藏的成员变量,也可以调用子类继承的方法或子类的重写方法(都来源于父类且等价于用子类对象去调用这些方法)
- 父类创建的对象和子类的上转型对象是相互独立的,互不相关的
- 对象的上转型对象可以强制转换到一个子类对象,该子类对象有具备了子类的所有属性和功能==(这时候子类对象就是下转型对象)==
- 不可以将父类创建的对象的引用赋值给子类对象
这里仍然采用刚刚的例子来说明:
package Chapter_5;
/**
* 测试多态
* @author 与猫子
*
*/
public class TestPolymorphism {
public static void main(String[] args) {
Animal a = new Animal();
animalShout(a);
Dog dog =new Dog();
animalShout(dog);//这里传递的是dog,是Dog的对象,
//Dog是Animal的子类
//dog传递给animalShout(Animal a)方法的父类引用(指Animal a)
//所以父类引用(Animal a)指向子类对象(dog),
//父类引用调用了子类重写的方法,此时多态出现
animalShout(new Cat());
Animal cat = new Cat();
//测试对象转型——上转型对象
Animal up_object = new Dog();
//编译器认为此时 up_object是Animal类,运行的时候才知道是Dog类而不是Animal类
/**up_object.name =null;**/ //编译错误,上转型对象无法操作子类新增的成员变量
dog.name="与猫子";
// up_object.speakName();//编译错误,上转型对象无法操作子类新增的方法
dog.speakName();
//测试下转型对象
Dog dog_2 = (Dog) up_object ;
dog_2.name="黑猫子";
dog_2.speakName();
//下转型对象又具备了子类的所有属性和功能
// Dog dog_3 = (Dog) cat ;
// dog_3.speakName();
//此时编译通过,但是运行时出现报错ClassCastException(即类型转化错误)
//编译器认为dog_3就是一个Dog类,事实上dog_3是一个Cat类
//dog_3.speakName_cat();
//编译错误,Dog类中没有方法speakName_cat()
}
static void animalShout(Animal a) {
a.shout();
}
//如果没有多态就需要多编写很多方法,如下,会出现大量重载的方法,代码臃肿
// static void animalShout(Dog dog) {
// dog.shout();
// }
//
// static void animalShout(Cat cat) {
// cat.shout();
// }
}
class Animal{
public void shout() {
System.out.println("叫了一声!");
}
}
class Dog extends Animal{//继承
//这里的成员变量属于子类新增的变量
int age;
String name;
String kind;
public void shout() {//方法的多态
System.out.println("汪汪汪!");
}
//这是子类新增的方法
public void speakName() {
System.out.println("我的名字是"+name+"!");
}
}
class Cat extends Animal{//继承
public void shout() {//方法的多态,指重写
System.out.println("喵喵喵!");
}
public void speakName_cat() {
System.out.println("我是猫");
}
}