Java多态
- 多态:(多种形态)是同一个行为具有多个不同表示形式或形态的能力,多态就是同一个接口,使用不同的实例而执行不同的操作.
优点
- 1.消除类型之间的耦合关系.
- 2.可替换性
- 3.可扩充性
- 4.接口性
- 5.灵活性
- 6.简化性
必要条件
- 1.继承
- 2.重写
- 3.父类引用变量指向子类对象
父类类型 变量名 = new 子类类型();
变量名.方法名();
- 普通类多态定义的格式
public class Zi extends Fu{}
public class Fu {}
Fu f = new Zi();
注意:
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误,如果有,再去调用子类的同名方法.使用多态的好处是:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理.
案例
/**
* 多态
*/
public class HelloPolymorphic {
public static void main(String[] args) {
// 以 Cat 对象调用 show 方法
show(new Cat());
// 以 Dog 对象调用 show 方法
show(new Dog());
// 向上转型:通过子类对象 (小范围) 实例化父类对象 (大范围),这种属于自动转换
Animal a = new Cat();
// 调用的是 Cat 的 eat
a.eat();
// 向下转型:父类强制转换为子类,从而调用子类独有的方法
Cat c = (Cat) a;
// 调用的是 Cat 的 work
c.work();
}
public static void show(Animal a) {
a.eat();
// 类型判断 比较运算符:instanceof 返回值的类型是boolean
if (a instanceof Cat) {
// 猫做的事情
Cat c = (Cat) a;
c.work();
}
// 狗做的事情
else if (a instanceof Dog) {
Dog c = (Dog) a;
c.work();
}
}
}
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
@Override
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
@Override
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}
- 输出的顺序
吃鱼
抓老鼠
吃骨头
看家
吃鱼
抓老鼠
实现方式
- 1.重写
- 2.接口
- 3.抽象类和抽象方法
多态- 成员的特点
- 前面学习继承时,我们知道子父类之间成员变量有了自己的特定变化,那么当多态出现后,会导致子父类中的成员变量有微弱的变化
public class Fu {
int num = 4;
public void show() {
System.out.println("Fu");
}
}
public class Zi extends Fu {
int num = 5;
public void show() {
System.out.println("Zi");
}
}
public class Demo {
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.num); // 4
f.show(); // Zi
}
}
- 调用方法看等号右边,调用属性看等号左边
附:扩展阅读
向上转型与向下转型
概述:
父子对象0之间的转换分为了向上转型和向下转型,它们的区别如下:
- 向上转型:通过子类对象(小范围)实例化父类对象(大范围),这种属于自动转换;
- 向下转型:通过父类对象(大范围)实例化子类对象(小范围),这种属于强制转换.
public class HelloUp{
public static void main(String[] args){
//通过子类去实例化父类
Fu f = new Zi();
a.print();//结果是:Zi:print
}
}
class Fu{
public void print(){
System.out.println("Fu:print")
}
}
class Zi extends Fu{
@Oerride
public void print(){
System.out.println("Zi:print")
}
}
- 可以看到打印的是
class Zi 的print
,这是因为我们通过子类Zi去实例化的,所以父类 Fu 的print方法已经被子类Zi的print方法覆盖了,从而打印class Zi 的print.
**注意**:其意义在于但我们需要多个同父的对象调用某个方法时,通过向上转换后,通过向上转换后,则可以确定参数的统一。方便程序设计
向下转型(instanceof)
在Java
中,向下转型则是为了通过父类强制转换为子类,从而调用子类特有的方法,为了保证向下转型的顺利完成,在Java
中提供一个关键字instanceof
通过 instanceof
可以判断某对象是否是某类的实例,如果是则返回 true
, 否则为 false
.
// 向上转型 (B 是 A 的子类)
A a = new B();
// 返回 true
a instanceof A;
// 返回 true
a instanceof B;
// 返回 false
a instanceof C;
package com.funtl.oop.demo5;
/**
* 向下转型
*/
public class HelloDown {
public static void func(A a) {
a.print();
if (a instanceof B) {
// 向下转型,通过父类实例化子类
B b = (B) a;
// 调用 B 类独有的方法
b.funcB();
} else if (a instanceof C) {
// 向下转型,通过父类实例化子类
C c = (C) a;
// 调用 C 类独有的方法
c.funcC();
}
}
public static void main(String args[]) {
func(new A());
func(new B());
func(new C());
}
}
class A {
public void print() {
System.out.println("A:print");
}
}
class B extends A {
@Override
public void print() {
System.out.println("B:print");
}
public void funcB() {
System.out.println("funcB");
}
}
class C extends A {
@Override
public void print() {
System.out.println("C:print");
}
public void funcC() {
System.out.println("funcC");
}
}
- 输出顺序如下
A:print
B:print
funcB
C:print
funcC
通过输出结果我们可以看到成功通过向下转型来调用 B 类和 C 类独有的方法