Java基础复习 Day 14
1. 多态
-
多态体现:就是一个对象既有父类的属性又有子类的属性(或者既有接口的方法,又有自己重写的方法等),体现出不同的形态,
多态的前提是继承(extends & implements)
-
多态的在代码中的应用:父类引用指向子类对象。
格式:父类名称 对象名 = new 子类名称();
or 接口名称 对象名 = new 实现类名称();
-
使用多态写法时,访问成员变量的两种方式:
-
直接:通过子类对象.成员变量 (父类 对象名 = new 子类();)此时等号左边是谁,就是先访问谁的成员变量,没有则向上找
-
间接:通过成员方法访问成员变量:该成员方法属于谁,就用谁的成员变量,没有则向上找
//父类 public class BasicDemo { int num = 300; public void method(){ System.out.println("父类的方法调用的成员变量: " + num); } } //子类 public class DerivedDemo extends BasicDemo { int num = 100; @Override public void method() { System.out.println("子类方法调用的成员变量: " + num); } } //Main函数 用多态方法 public static void main(String[] args) { BasicDemo basicDemo = new DerivedDemo(); //直接访问同名成员变量,.前面是谁就是谁 System.out.println(basicDemo.num);//300 //间接访问同名成员变量 //当子类没有重写同名父类方法时,则访问的是父类的同名成员变量 basicDemo.method(); //父类的方法调用的成员变量: 300 //当子类重写同名父类方法时,则访问的是子类的同名成员变量 //子类方法调用的成员变量: 100 }
-
-
成员方法的访问规则:看new的是谁就优先调用谁的方法,如果没有就向上找。
//父类 public class BasicDemo { int num = 300; public void methodBasic(){ System.out.println("父类特有的方法"); } public void method(){ System.out.println("父类方法"); } } //子类 public class DerivedDemo extends BasicDemo { int num = 100; @Override public void method() { System.out.println("子类重写方法"); } public void methodDerived(){ System.out.println("子类特有方法"); } } //Main方法 多态实现 /* * 成员变量:编译看左,运行看左 * 成员方法:编译看左,运行看右 * */ public class DemoMain1 { public static void main(String[] args) { BasicDemo basicDemo = new DerivedDemo(); basicDemo.method();//父子都有,优先调用子 basicDemo.methodBasic();//子类没有,向上找父类有则用父类的。 //编译报错 Cannot resolve symbol 'method' //编译看左,运行看右, 左边是父类,父类中没有methodDerived()所以编译直接报错 //basicDemo.methodDerived()// } }
-
多态的优点:
Basic basic = new Derived();
无论子类右边new的是什么对象,保证左边的变量都是同一个,并且左边调用的方法都是同一个,不用再改左侧代码,增加代码灵活性
-
对象的向上转型:其实就是多态写法
格式:父类名称 对象名 = new 子类名称(); Animal animal = new Cat();
含义:右侧创建了一个子类对象,但是把它当做父类来看待使用;创建了一只猫当做动物 没有问题
注意事项:向上转型一定是安全的。(从小范围转型为大范围)
弊端:如果子类的特有方法是没有办法被父类来调用的。
-
对象的向下转型:其实是还原的动作(有点像强制类型转换)
格式: 子类名称 对象名 = (子类名称)父类对象
Animal animal = new Cat(); 向下转型: Cat cat = (Cat)animal
含义:将父类对象还原成为本来的子类对象
注意事项:
- 必须保证对象在创建的时候是猫(new的是Cat), 才能正确的转型为猫
- 如果对象创建的时候不是猫,现在非要向下转型成猫,就会报错
//父类 public abstract class Animal { //这是一个抽象方法,代表吃东西,但是具体吃什么,内容不确定 public abstract void eat(); } //子类 public class Cats extends Animal{ @Override public void eat() { System.out.println("Cats eat fish!!!"); } } public class Dogs extends Animal { @Override public void eat() { System.out.println("dogs eat bones!!!!"); } } //向上转型和向下转型 public static void main(String[] args) { //对象的向上转型 Animal animal = new Cats(); animal.eat();//Cats eat fish!!! //对象的向下转型 Cats cat = (Cats) animal; cat.eat();//Cats eat fish!!! //编译不报错,运行报错ClassCastException类转换异常 Dogs dog = (Dogs) animal;//Exception in thread "main" java.lang.ClassCastException: com.kou.oop.demo11.Cats cannot be cast to com.kou.oop.demo11.Dogs dog.eat(); }
-
安全向下转型:instanceof
格式:
对象 instanceof 类型
这将会得到一个boolean的结果,来判断当前对象是不是想要向下转型的实例
//还是上边的子父类 //main方法中使用安全的向下转型,一般用于方法的参数或者返回值是父类或者接口 public static void main(String[] args) { //对象的向上转型 Animal animal = new Cats(); animal.eat();//Cats eat fish!!! //如果需要调用子类的特有方法,那么就要安全的向下转型 //对象的向下转型 避免转错,就得先判断 if (animal instanceof Dogs) {//由于animal不是Dogs的实例 所以不能向下转型 Dogs dog = (Dogs) animal; dog.eat(); } else if (animal instanceof Cats) { Cats cat = (Cats) animal; cat.eat();//Cats eat fish!!! } giveMePet(animal); } //方法的参数是抽象类 public static void giveMePet(Animal animal){ if (animal instanceof Dogs) {//由于animal不是Dogs的实例 所以不能向下转型 Dogs dog = (Dogs) animal; dog.eat(); } else if (animal instanceof Cats) { Cats cat = (Cats) animal; cat.eat();//Cats eat fish!!! } }