易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态
第8章 多态/8.1 再论向上转型
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
- 参照:
- 向上引用本质:对象引用为基类类型,实际为导出类类型
- 源代码例子:
-
package mypackage.music; import mypackage.music.*; import static mypackage.Print.*; public class Music { public static void tune(Instrument i) { i.play(Note.MiDDLE_C); } public static void main(String[] args) { // TODO Auto-generated method stub Wind fluteWind = new Wind(); tune(fluteWind); } }
-
package mypackage.music; import mypackage.music.*; import static mypackage.Print.*; public class Instrument { public void play(Note n) { print("Instrument.paly"); } }
-
package mypackage.music; import mypackage.music.*; import static mypackage.Print.*; public class Wind extends Instrument { public void play(Note n) { print("wind.play:" + n); } }
-
package mypackage.music; public enum Note { MiDDLE_C,C_SHARP,B_FLAT; }
-
- 输出结果:
- 源代码例子:
第8章 多态/8.1 再论向上转型/8.1.1 忘记对象类型
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
- 如果 Instrument 为导出类类型,而不是基类类型,会发生什么事情呢?
- 这样会导致 “class Music”需要为每一个 tune(Instrument i) 编写方法,这样虽然行得通,但是对于每增加一个导出类,都需要新增一个tune(Instrument i) 方法,这样会带来巨大的工作量和麻烦
-
举例:
第8章 多态/8.2 转机/8.2.1 方法调用绑定
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
第8章 多态/8.2 转机/8.2.2 产生正确的行为
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
-
-
举例:
-
动态绑定的例子
-
源代码:
-
package mypackage.shape; import java.util.Iterator; public class Shapes { private static RandomShape randomShape = new RandomShape(); public static void main(String[] args) { // TODO Auto-generated method stub Shape[] shape = new Shape[9]; for (int i = 0; i < shape.length; i++) { shape[i] = randomShape.next(); } for (Shape shape2 : shape) { shape2.draw(); // shape2.erase(); } } }
-
package mypackage.shape; import mypackage.Print; public class Shape { public void draw() { Print.print("Shape.dram"); } public void erase() { Print.print("Shape.erase"); } }
-
package mypackage.shape; import static mypackage.Print.*; public class Circle extends Shape { public void draw() { print("Circle.draw"); } public void erase() { print("Circle.erase"); } }
-
package mypackage.shape; import static mypackage.Print.print; public class Square extends Shape { public void draw() { print("Square.draw"); } public void erase() { print("Square.erase"); } }
-
package mypackage.shape; import java.util.Random; import mypackage.Print; public class RandomShape { private Random random = new Random(47); public Shape next() { int value = random.nextInt(3); // Print.print("value = " + value); switch (value) { case 0: return new Circle(); case 1: return new Shape(); case 2: return new Triangle(); default: return new Shape(); } } }
package mypackage.shape; import static mypackage.Print.print; public class Triangle extends Shape { public void draw() { print("Triangle.draw"); } public void erase() { print("Triangle.erase"); } }
-
- 输出结果:
-
源代码:
-
举例:
第8章 多态/8.2 转机/8.2.3 可扩展性
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
- 参照: 第8章 多态/8.1 再论向上转型
- 这时候再往
类中加入更多方法,同时导出类也添加通用的方法,没关系,
这个方法依旧可以使用,并且不用修改不用编译
- 扩展后的
类为:
第8章 多态/8.2 转机/8.2.4 覆盖私有方法
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
第8章 多态/8.2 转机/8.2.5 域与静态方法
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
-
- 尽管域是public的,但是也不是多态的
-
例子
-
源代码:
import mypackage.Print; class Super{ public int field = 0; public int getField(){ return field; } } class Sub extends Super{ public int field = 1; public int getField(){ return field; } public int getSuperField() { return super.field; } } public class FieldAccess { public static void main(String[] args) { // TODO Auto-generated method stub Super super1 = new Sub(); Print.print("super1.field = " + super1.field + ",super1.getField = " + super1.getField()); Sub sub = new Sub(); Print.print("sub.field = " + sub.field + ",sub.getField = " + sub.getField()); } }
- 输出结果:
-
源代码:
- 静态方法
- 尽管静态方法是public的,但是也不是多态的
- 例子
- 源代码:
- 输出结果:
- 源代码:
第8章 多态/8.3 构造器和多态/8.3.1 构造器的调用顺序
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
- 导出类和基类调用顺序: 第7章 复用类/7.9 初始化以及类的加载/7.9.1 继承和初始化
- 组合、继承、多态性构造顺序例子
-
源代码:
package polymorphism; import static mypackage.Print.*; class Meal { Meal() { print("Meal"); } } class Bread { Bread() { print("Bread"); } } class Cheese { Cheese() { print("Cheese"); } } class Letytuce { Letytuce() { print("Letytuce"); } } class Lunch extends Meal{ Lunch() { print("Lunch"); } } class PortableLunch extends Lunch{ PortableLunch() { print("PortableLunch"); } } public class Sandwich extends PortableLunch{ private Bread bread = new Bread(); private Cheese cheese = new Cheese(); private Letytuce letytuce = new Letytuce(); public Sandwich(){ print("Sandwich"); } public static void main(String[] args) { // TODO Auto-generated method stub new Sandwich(); } }
- 输出结果:
-
第8章 多态/8.3 构造器和多态/8.3.2 继承和清理
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
- 通常使用dispose方法来清理,dispose调用顺序更好与对象引用声明顺序相反,参照: 第7章 复用类/7.4 结合使用组合和继承/7.4.1 确保正确清理
- 举例子:
- 源代码:
package polymorphism; import static mypackage.Print.*; class Characteristic{ //Characteristic:特征/特点 private String s; Characteristic(String s){ this.s = s; print("Characteristic:" + s); } protected void dispost() { print("dispost:" + s); } } class Description{ //Description:描述 private String s; Description(String s){ this.s = s; print("Description:" + s); } protected void dispost() { print("Description:" + s); } } class LivingCreature{ //LivingCreature:生物 private Characteristic pCharacteristic = new Characteristic("is alive"); private Description pDescription = new Description("Basic Living Creature"); LivingCreature(){ print("LivingCreature"); } protected void dispost() { print("LivingCreature dispost" ); pDescription.dispost(); pCharacteristic.dispost(); } } class Animal extends LivingCreature{ private Characteristic pCharacteristic = new Characteristic("has heart"); private Description pDescription = new Description("Animal not vegetable"); Animal(){ print("Animal"); } protected void dispost() { print("Animal dispost" ); pDescription.dispost(); pCharacteristic.dispost(); super.dispost(); } } class Amphibian extends Animal{ //两栖动物 private Characteristic pCharacteristic = new Characteristic("can live in water"); private Description pDescription = new Description("both water and land"); Amphibian(){ print("Amphibian"); } protected void dispost() { print("Amphibian dispost" ); pDescription.dispost(); pCharacteristic.dispost(); super.dispost(); } } public class Forg extends Amphibian{//青蛙 private Characteristic pCharacteristic = new Characteristic("Croaks"); private Description pDescription = new Description("Eats Bugs"); public Forg(){ print("Forg"); } protected void dispost() { print("Forg dispost" ); pDescription.dispost(); pCharacteristic.dispost(); super.dispost(); } public static void main(String[] args) { // TODO Auto-generated method stub Forg forg = new Forg(); print("bye"); forg.dispost(); } }
- 结果输出:
- 源代码:
第8章 多态/8.3 构造器和多态/8.3.3 构造器内部的多态方法的行为
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
-
- 如果构造器中绑定了多态的方法,那将会发生什么事情呢?
-
举例:
-
源代码:
,因为调用顺序为:
package polymorphism; import static mypackage.Print.*; class Glyph { //图象字符 void draw(){ print("Glyph draw"); } Glyph(){ print("Glyph before"); draw(); print("Glyph after"); } } class RoundGlyph extends Glyph{ //圆形符号 private int radius = 1; RoundGlyph(int r){ radius = r; print("RoundGlyph radius = " + radius); } void draw(){ print("RoundGlyph radius = " + radius); } } public class PolyConstructors { public static void main(String[] args) { // TODO Auto-generated method stub new RoundGlyph(5); } }
- 输出结果:
-
源代码:
- 结论
- 构造器应该足够简单,只进行初始化成员域即可,尽量不要调用方法
- 如果要调用方法也是调用final方法或者private方法,因为这些方法不会被覆盖
第8章 多态/8.4 协变返回类型
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
第8章 多态/8.5 用继承进行设计/8.5.1 纯继续与扩展
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
第8章 多态/8.5 用继承进行设计/8.5.2 向下转型与运行时类型识别
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
第8章 多态/8.6 总结
标签: | 作者:易学笔记 更多资料请联系微信或QQ:1776565180 |
-
前期绑定还是后期绑定:第8章 多态/8.2 转机/8.2.1 方法调用绑定
- 对于C语言,没有方法重载,所以所有的C语言都是前期绑定的;
- 对于Java,除了final和static方法,都是动态绑定的
- 因为final方法只能在本类使用,static方法只能属性声明类或者导出类类名调用。
- 如果是向上转型对象调用static方法,那么调用的都是对象声明类型对应的方法(通常就是基类的方法)
- 域是不能多态的,也就是基类和导出类的域是分开存储的
- 如果多态发生在基类构造方法中,那调用的方法是导出类的,但是导出类的初始化在基类后面,那该方法有可能用了未初始化的变量,那是非常危险的