Java语法之多态
Java语法之多态
多态简单来说就是:同一个接口,使用不同的实例而执行不同操作。(相同的事物,调用其相同的方法,参数也相同时,但表现的行为却不同。)比如F1 键这个动作:如果当前在 Flash 界面下弹出的就是AS3的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。
1、多态的前提和体现
- 有继承/实现关系(继承是多态的前提,没有继承就不会有多态)
- 有方法重写(有相同的方法)
- 有父类引用指向子类对象
public class Animals { //父类
public void eat(){
System.out.println("动物吃东西");
}
}
public class Cat extends Animals{ //子类,有继承关系
@Override
public void eat() { //有方法重写
System.out.println("猫吃鱼");
}
}
public class AnimalsDemo {
Animals a=new Cat(); //有父类引用指向子类对象
}
2、多态中变量的访问特点
public class Animals {
public int age=40; //父类的成员变量age
public void eat(){
System.out.println("动物吃东西");
}
}
public class Cat extends Animals{
public int age=20; //子类的成员变量age
public int weight=10;
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void playGame(){
System.out.println("猫捉迷藏");
}
}
public class AnimalsDemo {
public static void main(String[] args) {
Animals a=new Cat();
System.out.println(a.age);
a.eat();
}
}
对于Animals a=new Cat();
通过多态去访问成员变量的时候访问的是父类中的(左边),编译和运行都看左边;而执行成员方法的时候执行的是子类中的(右边)。
即:用父类作为参数,而真正执行方法的时候执行的是子类的方法。
3、深入理解多态
首先定义一个父类Animals
,两个子类,分别为:Cat
类和Dog
类。
Animal
类中有eat()
方法,用来表示动物吃东西
的动作,而在Cat
类和Dog
类中重写了eat()
方法,表征子类的特征,分别为猫吃鱼
和狗吃骨头
。
public class Animals {
public void eat(){
System.out.println("动物吃东西");
}
}
public class Cat extends Animals{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public class Dog extends Animals {
public void eat() {
System.out.println("狗吃骨头");
}
}
为了统一化,新建一个AnimalsOperator
类来集中统计各种动物对于吃东西这一动作的具体表现形式,例如:猫吃鱼、狗吃骨头等。(将目标子类对象作为方法的参数)
public class AnimalsOperator {
public void useAnimal(Cat c){
c.eat();
}
public void useAnimal(Dog d){
d.eat();
}
}
现定义主方法,构造了一个AnimalsOperator
对象、一个Cat
对象,一个Dog
对象,调用useAnimal
方法来执行。
public class AnimalsDemo {
public static void main(String[] args) {
AnimalsOperator ao=new AnimalsOperator();
Cat c=new Cat();
ao.useAnimal(c);
Dog d=new Dog();
ao.useAnimal(d);
}
}
输出结果显而易见:
上述代码中,只有猫和狗两种,如果再加一种动物,那么按照以上代码的逻辑,就需要在AnimalOperator
中继续再增加一个方法,非常麻烦,因此可以对以上代码用多态来改进:
public class AnimalsOperator {
public void useAnimal(Animal a){
//父类作为参数去接收
a.eat();
}
}
public class AnimalsDemo {
public static void main(String[] args) {
AnimalsOperator ao=new AnimalsOperator();
Animals c=new Cat();//用父类去接收新定义的子类
ao.useAnimal(c);//用父类去传参,但实现子类的方法
Animals d=new Dog();
ao.useAnimal(d);
}
}
改进后,就用父类去作为参数去接收,而执行方法的时候执行的是具体子类的方法,这就相当于父类作为一个公用的接口,去向外提供,而具体实现的方法是子类的方法。
以上是多态的好处,而在这个例子中,多态存在弊端,就是对于子类特有的方法无法实现。
4、多态中的转型
多态有一个弊端就是不能使用子类特有的功能,而转型就可以实现这一目标,从而使用子类特有的功能。
public class Cat extends Animals{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void plagGame(){
System.out.println("猫捉迷藏");
}
}
public class Animals {
public void eat(){
System.out.println("动物吃东西");
}
}
(1)向上转型
从子到父——>把子类对象赋值给父类对象——>向上转型。
public class AnimalsDemo {
public static void main(String[] args) {
Animals a=new Cat(); //把子类对象赋值给父类对象————>向上转型
a.eat();
}
}
在该例子中,虽然可以输出"猫吃鱼",但是由于父类无法实现子类的特有功能,所以无法实现”猫捉迷藏“的方法,因此需要向下转型。
(2)向下转型
从父到子——>把父类对象强制转换为子类对象——>向下转型
public class AnimalsDemo {
public static void main(String[] args) {
Animals a=new Cat();
Cat c=(Cat)a; //把父类对象强制转换为子类对象————>向下转型
c.plagGame(); //实现子类特有的方法
}
}