java-多态
来源:互联网 发布:jmeter调用java代码 编辑:程序博客网 时间:2024/06/10 15:33
多态的作用是消除类型之间的耦合性,它允许将多种类型(从同一个基类导出的)视为同一类型来处理。让代码只操纵基类,这样,如果要添加一个新类,也不影响到原来的代码
一、向上转型
把某个对象的引用视为对其基类型的引用的做法称作向上转型
class Food{ public void cook(){ System.out.println("Food is cooking."); }}class Cake extends Food{ public void cook() { System.out.println("Cake is cooking."); }}public class Restaurant { public static void cook(Food food){ food.cook(); } public static void main(String[] args) { Cake cake = new Cake(); cook(cake); }}
Restaurant.cook()方法接受Food的引用,同时也接受任何导出自Food的类。Cake从Food继承而来,所以Food的方法存在在Cake中,所以可以将Cake的引用传递给Food。如果cook()方法直接接受一个Cake作为引用,之后每次添加新的子类的时候,都需要重新编写一个cook()方法。
我们可以根据自己的需求对系统添加多个新类型,但是却不需要改变cook()方法。只有基类接口通信,操纵基类接口的方法不需要改动就可以应用新类。
二、方法调用绑定
接受基类引用的时候,编译器无法知道这是基类还是引用。
默认的绑定方法为前期绑定,java当中的方法只有final,static,private和构造方法是前期绑定
后期绑定(动态绑定)
在运行时根据对象的类型进行绑定,编译器一直不知道对象的类型,但是方法调用机制能找到正确的方法体,并加以调用。
class Food{ public void cook(){ System.out.println("Food is cooking."); }}class Cake extends Food{ public void cook() { System.out.println("Cake is cooking."); }}class Biscuit extends Food{ public void cook(){ System.out.println("biscuit is cooking."); }}class Apple extends Food{ public void cook(){ System.out.println("apple is cooking."); }}class FoodGenerator{//是一个工厂,随机的返回一个引用 private Random random = new Random(47); //调用next()方法时无法知道具体类型是什么 public Food next(){ switch(random.nextInt(3)){ default: case 0:return new Cake(); case 1:return new Biscuit(); case 2:return new Apple(); //在return时产生向上转型 } }}public class Restaurant { private static FoodGenerator foodGenerator = new FoodGenerator(); public static void main(String[] args) { Food[] foods = new Food[5]; for (int i = 0; i < foods.length; i++) { foods[i] = foodGenerator.next(); } for (Food food : foods) { food.cook(); } }}
输出:
apple is cooking.apple is cooking.biscuit is cooking.apple is cooking.biscuit is cooking.
编译器不需要获得任何特殊信息就能进行正确的调用,对cook()方法的调用都是动态绑定进行的
三、缺陷
1、private方法被自动认为是final方法,而且对导出类是屏蔽的,所以不能被重载
public class DefectDemo { private void f(){ System.out.println("private f()."); } public static void main(String[] args) { DefectDemo defectDemo = new Defect1(); defectDemo.f(); }}class Defect1 extends DefectDemo{ public void f(){ System.out.println("public f()."); }}
输出
private f().
Defect1类中的f()方法被认为是一种全新的方法。所以调用的仍然是基类的f().
2、域和静态方法
任何域访问操作都由编译器解析,因此不是多态的。
如果某个方法是静态的,它的行为就不具有多态的,静态方法是与类,而并非与单个的对象相关联的。
四、构造器和多态
调用构造器遵循的顺序
1)在其他任何事物发生之前,将分配给对象的储存空间初始化成二进制的零。
2)调用基类构造器
3)按照声明的顺序调用成员的初始化方法
4)调用导出类的构造器主体
class Meal{ void cook(){ System.out.println("Meal is cooking"); } public Meal() { System.out.println("Meal before cook"); cook(); System.out.println("Meal after cook"); }}class Fish extends Meal{ private int num = 2; public Fish(int num) { this.num = num; System.out.println("Fish.Fish(), num = " + num); } void cook(){ System.out.println(num + " Fishes is cook"); }}public class PolyMethod { public static void main(String[] args) { new Fish(3); }}
结果:
Meal before cook0 Fishes is cookMeal after cookFish.Fish(), num = 3
在一个构造器的内部调用了正在构造的对象的某个动态绑定方法,用到了被覆盖后的方法,但是它还没有初始化,所以才会输出0 Fishes is cook
,一个动态绑定的方法调用会向外深入到继承层次结构内部,它可以调用导出类里的方法。
编写构造器时的一条准则
用尽可能简单的方法是对象进入正常状态,如果可以的话,避免调用其他方法
在清理时,如果某个子对象要依赖于其他对象,销毁的顺序应该和初始化的顺序相反,先对导出类清理,然后才是基类。可以引入计数来跟踪仍旧访问着共享对象的对象数量。
- Java学习 java -- 多态
- java多态
- java多态
- java多态
- java多态
- Java多态
- java多态
- JAVA@多态
- Java多态
- java 多态
- Java多态
- java多态
- [Java] 多态
- JAVA多态
- Java多态
- java多态
- java 多态
- java多态
- Leetcode 76. Minimum Window Substring(Hard)
- Unity下关于C#的文件读写二(文件夹的读取)
- 动态集合 字典
- Java网络爬虫crawler4j学习笔记<2> Util类
- MarkDown 超链接页面内和通过新窗口打开
- java-多态
- <设计模式21>访问者模式
- 继承
- JS数据类型
- JavaScript中的this
- opencv-python 函数总览(初版)
- 通用的IO流文件读取工具
- 183Q游戏(16)188/193/198/202/206/210/214(17-23)
- 功分器和耦合器以及合路器的区别