> 文章列表 > JavaSE基础(23) 多态

JavaSE基础(23) 多态

JavaSE基础(23) 多态

概念

多态是继封装、继承之后,面向对象的第三大特性。

生活中,比如跑的动作,小猫、小狗和大象,跑起来是不一样的。再比如飞的动作,昆虫、鸟类和飞机,飞起来也是不一样的。可见,同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。

多态 (多种形态) 是同一个行为具有多个不同表现形式或形态的能力,多态就是同一个接口,使用不同的实例而执行不同操作

父类类型 变量名 = new 子类对象;
变量名.方法名();
父类类型:指子类对象继承的父类类型,或者实现的父接口类型。

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的重写方法。

使用多态的好处是,可以使程序有良好的扩展,并可以对所有类的对象进行通用处理

实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展性与便利。

public class Animal {public void run(){System.out.println("动物跑起来......");}
}
class Cat extends Animal{@Overridepublic void run(){System.out.println("猫跑起来.....");}public void catchMouse(){System.out.println("抓老鼠......");}}class Dog extends Animal{@Overridepublic void run(){System.out.println("狗狗跑起来......");}public void keepDoor(){System.out.println("看门........");}
}public class Demo_Polymorphic {public static void show(Animal a){//会根据传入的参数的不同,调用不同的子类重写的方法,体现了多态的特征a.eat();//分别调用子类的重写,体现了多态的特征}public static void main(String[] args){show(new Animal());show(new Cat());//以Cat为对象调用show方法;show(new Dog());//以Dog为对象调用show方法;}
}

引用类型转换

父子对象之间的转换分为了向上转型和向下转型 , 它们区别如下:

向上转型: 通过子类对象 (小范围) 实例化父类对象 (大范围),这种属于自动转换

注意: 其意义在于当我们需要多个同父的对象调用某个方法时,通过向上转换后,则可以确定参数的统一。方便程序设计

对象的向上转型(安全的):会失去子类新增。 子类对象,被看做了父类的类型。那么就不能访问子类的新增, 只能访问父类的属性和方法。以及子类重写。

/* 向上转型案例*/
public class HelloUp {public static void main(String args[]) {// 通过子类去实例化父类A a = new B();a.print();}
}
class A {public void print() {System.out.println("A:print");}
}class B extends A {@Overridepublic void print() {System.out.println("B:print");}
}

向下转型: 通过父类对象 (大范围) 实例化子类对象 (小范围),这种属于强制转换

为什么要转型

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有,而父类没有的方法。

编译都错误,更别说运行了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做向下转型。

instanceof关键字

在 Java 中,向下转型则是为了,通过父类强制转换为子类,从而来调用子类独有的方法,为了保证向下转型的顺利完成,在 Java 中提供

了一个关键字 instanceof, 通过 instanceof 可以判断某对象是否是某类的实例,如果是则返回 true, 否则为 false

instanceof:判断某个对象是否是某个类的实例:类以及继承的父类

// 向上转型 (B 是 A 的子类)
A a = new B();// 返回 true
a instanceof A;
// 返回 true
a instanceof B;
// 返回 false
a instanceof C;class A{public void print(){System.out.println("print:A");}
}class B extends A{@Overridepublic void print(){System.out.println("print:B");}public void funB(){System.out.println("funB().....");}
}class C extends A{@Overridepublic void print(){System.out.println("print:C");}public void funC(){System.out.println("funC().....");}
}

父类 对象1 = new 父类();

子类 对象2 = new 子类();

父类 对象3 = new 子类();

结论:

看一个对象能够访问哪些成员,看=左边是定义的是什么类型

        父类类型:只能访问父类的属性和方法,

        子类类型:可以访问父类的属性和方法,子类新增,子类重写

看一个对象最终访问哪个方法,看=右边是什么类型的对象

        父类对象:父类属性和方法

        子类对象:父类的属性和方法,以及子类重写的方法