JAVA中面向对象-对象的多态 与 多态类型判断 以及 多态成员的特点
对象的多态
例子:
class 动物
{}
class 猫 extends 动物
{}
class 狗 extends 动物
{}
猫 x = new 猫();
动物 x = new 猫();
一般一个对象两种形态,我们就可以认为是多态了
例如:动物 x = new 猫();
猫这类事物即具备猫的形态,又具备着动物的形态.
这就是对象多态性
简单说:就是一个对象对应着不同类型
左边是动物,右边是猫,两种形态,我们就可以说它是多态的
多态在代码的体现:
父类或者接口的引用指向其子类的对象
多态的好处:
提高了代码的扩展性.前期定义的代码可以使用后期的内容
多态的弊端:
前期定义的内容不能使用(调用)后期子类的特有内容.
多态的前提:
1.必须有关系,继承,实现
2.要有覆盖
例子:
abstract class Animal
{
abstract void egt(); //吃东西
}
class Dog extends Animal
{
void egt()
{
System.out.println("啃骨头");
}
void lookHome()
{
System.out.println("看家");
}
}
class Cat extends Animal
{
void egt()
{
System.out.println("吃鱼");
}
void catchMouse()
{
System.out.println("抓老鼠");
}
}
public class DuoTaiDemo {
public static void main(String[] args){
Animal a = new Cat();
//自动类型提升,猫对象提升了动物类型.但是特有功能无法访问.
//作用就是限制对特有功能的访问.
//专业讲:向上转型.
a.egt();
//c.catchMouse();//报错
method(a);//这样可以提高代码的复用性,如果继续new别的对象的时候,也能用
//如果还想用具体动物猫的特有功能.
//你可以讲该对象进行向下转型.
Cat c = (Cat)a;//向下转型是为了使用子类中的特有方法.
c.egt();
method(c);//这样可以提高代码的复用性,如果继续new别的对象的时候,也能用
c.catchMouse();//猫的特有功能(方法)
//注意: 对于转型, 自始至终都是子类对象在做类型的变化.
//Animal a1 = new Dog();
//Cat c1 = (Cat)a1;
//报错: ClassCastException 类型转换异常
//这里是Dog类型向上转型,然后把它向下转型为Cat...
}
public static void method(Animal a) //Animal a = new 不同子类对象()
{
a.egt();
}
}
.
.
.
多态类型判断
关键字: instanceof
例子:
public static void method(Animal a) //Animal a = new 不同子类对象()
{
a.egt();
if(a instanceof Cat)
{
Cat b = (Cat)a;
b.catchMouse();
}
else if(a instanceof Dog)
{
Dog b = (Dog)a;
b.lookHome();
}
//这样挨个判断的几乎没有...
}
关键字instanceof
:
用于判断对象的具体类型.只能用于引用数据类型判断
通常在向下转型前用于健壮性的判断.
一般在我们转型的时候判断,让它给我们反馈.
.
.
.
多态成员的特点
1.成员变量
例子:
class Fu
{
int num = 3;
}
class Zi extends Fu
{
int num = 4;
}
public class Demo {
public static void main(String[] args){
Fu f = new Zi();
System.out.println(f.num);
}
}
结果:
因为Zi类,向上转型为Fi类
所有f.num
就是调用父类的num
不过一般开发不这样弄,因为都已经有了,直接调用就完事了…
面试可能会问到
.
.
.
2.成员函数
例子:
class Fu
{
void show()
{
System.out.println("fu show");
}
}
class Zi extends Fu
{
void show()
{
System.out.println("zi show");
}
}
public class Demo{
public static void main(String[] args){
Fu f = new Zi();
f.show();
}
}
结果:
为什么会输出zi show
图解:
刚开始主函数main进栈
然后f new Zi()
Zi类继承了Fu类,他们两个一起进入了方法区
接着创建了一个对象,并分配了地址
再然后把地址给到变量f, f指向对象在堆内存的地址
接着f调用了show()方法
这时就会先在Zi类
找show()
方法,发现有,就输出了—zi show
假设Zi类
没有show()
方法,那么就是通过super
进入Fu里面找show()
方法
Fu还没有的话,就直接报错了
.
.
.
3.静态函数
例子:
class Fu
{
static void method()
{
System.out.println("fu static method");
}
}
class Zi extends Fu
{
static void method()
{
System.out.println("zi static method");
}
}
public class Demo{
public static void main(String[] args){
Fu f = new Zi();
f.method();
}
}
结果:
为什么会输出:zi static method
图解:
刚开始与前面差不多
不同的是这里的静态方法是加载进静态的方法区
全部好了之后执行下面的语句调用了静态方法f.method();
这时因为Zi类向上转型,于是变成了Fu类的.
于是就调用了Fu类的静态方法了,输出:fu static metheod
了
如果是 Zi f = new Zi();
那么执行静态方法f.method();
的时候,就输出:zi static metheod
了
其实如果我们调用静态方法时,不需要用到对象时,可以直接通过类进行调用进行了
例如:
Fu.method();
Zi.method();
.
.
.
通过上面三个例子我们可以得出多态成员的特点
1.成员变量
编译时:参考引用型变量所属的类中的是否有调用的成员变量,有,编译通过,没有,编译失败.
运行时:参考引用型变量所属的类中的是否有调用的成员变量,并运行该所属类中的成员变量.
简单说:编译和运行都参考等号的左边.
作为了解就行了
2.成员函数(非静态)
编译时:参考引用型变量所属的类中的是否有调用的成员函数.有,编译通过, 没有, 编译失败.
运行时:参考的是对象所属的类中是否有调用的函数.
简单说:编译看左边,运行看右边
3.静态函数
编译时:参考引用型变量所属的类中的是否有调用的静态方法.
运行时:参考引用型变量所属的类中的是否有调用的静态方法.
简单说:编译和运行都看左边
其实对于静态方法,是不需要对象的,直接用类名调用即可.
推荐阅读
-
php学习笔记 面向对象中[接口]与[多态性]的应用
-
对继承与多态、成员变量的隐藏和方法重写、super关键字、final关键字、对象的上转型对象、抽象类的学习理解(java)
-
php学习笔记 面向对象中[接口]与[多态性]的应用_php基础
-
php学习笔记 面向对象中[接口]与[多态性]的应用_PHP
-
php学习笔记 面向对象中[接口]与[多态性]的应用_PHP
-
php学习笔记 面向对象中[接口]与[多态性]的应用_php入门_脚本之
-
php学习笔记 面向对象中[接口]与[多态性]的应用_PHP教程
-
Java中面向对象的特征之三(多态)
-
java入门基础 进阶篇————面向对象中的多态
-
java:面向对象-多态中的成员访问特点之成员变量