1 定义
代码当中体现多态性,其实就是一句话:父类引用指向子类对象。
2 格式
父类名称 对象名 = new 子类名称();
或
接口名称 对象名 = new 实现类名称();
public class Fu {
public void method(){
System.out.println("父类方法");
}
public void methodFu(){
System.out.println("父类特有方法");
}
}
public class Zi extends Fu{
@Override
public void method(){
System.out.println("子类方法覆盖重写父类方法");
}
}
public class Multi {
public static void main(String[] args) {
//使用多态的写法
//左侧父类的引用,指向了右侧子类的对象
Fu obj=new Zi();
obj.method();
obj.methodFu();
}
}
3 利用多态性访问成员变量与成员方法
3.1 访问成员变量的两种方式
1.直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找。
2.间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找。
口诀:编译看左边,运行看右边
public class Fu {
int num=10;
public void showNum(){
System.out.println(num);
}
}
public class Zi extends Fu{
int num=20;
int age=30;
public void showNum(){
System.out.println(num);
}
}
public class Multi {
public static void main(String[] args) {
//使用多态的写法,父类引用指向子类对象
Fu obj =new Zi();
System.out.println(obj.num);
// System.out.println(obj.age);//错误写法
obj.showNum();//子类没有覆盖重写,就是父,10;子类如果覆盖重写,就是子,20
}
}
输出:
3.2 访问成员方法的方式
看new的是谁,就优先用谁,没有就向上找。
口诀:编译看左边,运行看右边
public class Fu {
public void method(){
System.out.println("父类方法");
}
public void methodFu(){
System.out.println("父类特有方法");
}
}
public class Zi extends Fu{
@Override
public void method(){
System.out.println("子类方法覆盖重写父类方法");
}
public void methodZi(){
System.out.println("子类特有方法");
}
}
public class Multi {
public static void main(String[] args) {
//使用多态的写法
//左侧父类的引用,指向了右侧子类的对象
Fu obj=new Zi();
obj.method();//父子都有,优先用子
obj.methodFu();//子类没有,父类有,向上找到父类
//编译看左边,左边是Fu,Fu当中没有method方法,所以编译报错
// obj.methodZi();
}
}
输出:
4 使用多态的好处
5 对象的转型
5.1 对象的向上转型
向上转型的缺点:
一旦向上转型为父类,就无法调用子类原本特有的方法。
解决方案:
用对象的向下转型【还原】
5.2 对象的向下转型
public abstract class Animal {
public abstract void eat();
}
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse(){
System.out.println("猫捉老鼠");
}
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃Shit");
}
public void watchHouse(){
System.out.println("狗看家");
}
}
public class DemoMain {
public static void main(String[] args) {
//对象的向上转型,就是,父类引用指向子类对象
Animal animal=new Cat();
animal.eat();
// animal.catchMouse();//错误写法
//向下转型,进行“还原”动作
Cat cat=(Cat) animal;
cat.catchMouse();//猫抓老鼠
//下面是错误的向下转型
//Dog dog=(Dog) animal;//错误写法,编译不会报错,但是运行会出现异常ClassCastException
}
}
输出:
如何知道一个父类引用的对象,本来是什么样子?
对象 InstanceOf 类名称
这将会得到一个boolean值结果,也就是判断前面的对象能不能当做后面类型的实例。
public abstract class Animal {
public abstract void eat();
}
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse(){
System.out.println("猫捉老鼠");
}
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃Shit");
}
public void watchHouse(){
System.out.println("狗看家");
}
}
public class InstanceOf {
public static void main(String[] args) {
Animal animal =new Cat();
animal.eat();//猫吃鱼
giveMeAPet(animal);
}
public static void giveMeAPet(Animal animal){
//如果希望调用子类特有方法,需要向下转型
//判断一下父类引用animal本来是不是dog
if (animal instanceof Dog){
Dog dog=(Dog) animal;
dog.watchHouse();
} else if (animal instanceof Cat) {
Cat cat=(Cat) animal;
cat.catchMouse();
}
}
输出: