【从零开始学Java笔记】多态
大家可以关注作者的账号,关注从零开始学Java笔记文集。也可以根据目录前往作者的博客园博客进行学习。本片文件将基于黑马程序员就业班视频进行学习以及资料的分享,并记录笔记和自己的看法。欢迎大家一起学习和讨论。
【从零开始学Java笔记】目录
什么是多态?
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。一句话来说就是,多态是同一个行为具有多个不同表现形式或形态的能力。如果这里还不懂,不要紧,现急需往下看。
多态的前提
1.子父类的继承关系
2.方法的重写
3.父类引用指向子类对象
格式:
1.父类引用Animal a
2.指向=
3.子类对象new Cat( )
示例
对不同类的对象发出相同的消息将会有不同的行为。比如,一个铲屎官每天早上需要给自己家的宠物喂食,铲屎官只需要在规定时间下达命令:“开始吃饭”即可,而不需要对猫说:“开始吃鱼”,对狗说:“开始吃骨头”, 因为“宠物”是一个抽象的事物, 只要是宠物就可以吃东西,但是只要他知道自己吃什么就行了。
public class PolymorphicDemo {
public static void main(String[] args) {
Animal a = new cat();
a.eat();
}
}
class Animal{
public void eat(){
System.out.println("动物吃食物");
}
}
class cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
输出结果
猫吃鱼
虽然a指向的是父类Animal,但是调用的确实子类的eat()方法,这就是动态绑定。
动态绑定:运行期间调用的方法,是根据其具体的类型
多态的成员特点
成员变量编译时看的是左边,运行时看的左边
成员方法编译时看的是左边,运行时看右边
静态方法编译时看的是左边,运行时看的也是左边(使用变量去调用静态方法,其实相当于用变量类型的类名去调用)
public class Polymorphic {
public static void main(String[] args) {
Dad d = new Son();
System.out.println(d.num);
d.method();
d.function();
}
}
class Dad{
//没有会报错
int num = 20;
public void method() {
System.out.println("爸爸的方法");
}
public static void function() {
System.out.println("爸爸的静态方法");
}
}
class Son extends Dad{
int num = 10;
public void method() {
System.out.println("儿子的方法");
}
public static void function() {
System.out.println("儿子的静态方法");
}
}
输出结果
20
儿子的方法
爸爸的静态方法
总结:编译时看的都是左边(编译错误,就是在编译之前并没用建立对象,就是说父类并没有子类的方法,所有必须父类有子类的方法,子类重写才能运行通过),运行时成员方法看的是右边(动态绑定),其他(成员变里和静态的方法)看的都是左边(没有动态绑定)
多态中的向上转型和向下转型:
引用类型之间的转换
向上转型:由小到大(子类型转换成父类型)
向下转型:由大到小
基本数据类型的转换
自动类型转换
由小到大:byte short char --- int --- long --- float --- double
强制类型转换
由大到小
public class PolymorphicDemo1 {
public static void main(String[] args) {
Animal2 a = new Dog();//向上转型
// a.swim();//无法调用
Dog d = (Dog) a;//向下转型
d.swim();
}
}
class Animal2{
public void eat() {
System.out.println("吃东西");
}
}
class Dog extends Animal2
{
public void eat() {
System.out.println("啃骨头");
}
public void swim() {
System.out.println("游泳");
}
}
多态的优缺点
优点:可以提高可维护性(多态前提所保证的),提高代码的可扩展性
缺点:无法直接访问子类特有的成员
多态的作用
- 应用程序不必为每一个派生类编写功能调用,只需要对抽象基类进行处理即可。大大提高程序的可复用性。
- 派生类的功能可以被基类的方法或引用变量所调用,这叫向后兼容,可以提高可扩充性和可维护性。
一些疑惑
其实作者在刚学习多态的时候一直不理解多态有什么用?总感觉多此一举,因为子类重写了父类的方法,那为什么不直接实例子类或者父类?这样不仅可以使用子类的方法,子类还继承了父类,还能调用父类的方法。
其实作者认为这里原因有二,一是初学多态的时候,示例总是过于简单,例如本文之前猫吃鱼的例子,确实完全不需要多态反而更方便。二就是继承和多态没有分清楚,上述问题全是基于继承的一种想法去思考,然后发现多态和继承没有区别。
这里再给大家举个例子:
当有一个基类,比如说形状类Shape,然后其有一个方法getDesc()
获得其描述。Shape的子类Circle,Triangle,各自重载其父类的getDesc()
方法,Circle的getDesc()
返回“我是圆形”,Triangle的getDesc()
返回“我是三角形”。然后某一个类的某一个方法如下:
String test(Shape shape){
return shape.getDesc();
}
你在调用test()
方法时可里往里面传的参数类型可以是Shape、Circle或Triangle,多态能够保证getDesc()
方法被正确调用,这叫动态绑定,从而你不用写三个如下的方法,即test(Shape s)
,test(Circle c)
,test(Triangle t)
。
就可以理解了,多态是为了实现对一个元素进行操作就能满足所有这个元素子类的操作需求。这也就是为什么多态只能使用父类的方法,同时在调用时动态绑定实例出来的子类。因为像形状的例子例子中,以参数的形势接收父类,编译父类的方法,在运行时动态绑定相应的子类。即可达到目标。
如果任然不理解,还是没有问题,因为多态本身就是一个非常抽象的概念。在后期不断地深入学习中,带着问题去解决问题,慢慢就会拨开云雾见青天。然后也会慢慢体会多态的神奇魅力。