易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态

 

第8章 多态/8.1 再论向上转型

标签: 作者:易学笔记  更多资料请联系微信或QQ:1776565180

 

  1. 参照:
    1. 第7章 复用类/7.7 向上引用
    2. 第7章 复用类/7.7 向上引用/7.7.1 为什么称为向上引用
    3. 第7章 复用类/7.7 向上引用/7.7.2 再论组合和继承
  2. 向上引用本质:对象引用为基类类型,实际为导出类类型
    1. 源代码例子:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态
      1. 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);
        	}
        
        }
        

         

      2. package mypackage.music;
        
        import mypackage.music.*;
        import static mypackage.Print.*;
        
        public class Instrument {
          public void play(Note n) {
        	print("Instrument.paly");
         }
        }
        

         

      3. package mypackage.music;
        
        import mypackage.music.*;
        import static mypackage.Print.*;
        
        public class Wind extends Instrument {
        	public void play(Note n) {
               print("wind.play:" + n);
        	}
        }
        

         

      4. package mypackage.music;
        
        public enum Note {
           MiDDLE_C,C_SHARP,B_FLAT;
        }
        

         

    2. 输出结果:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态

第8章 多态/8.1 再论向上转型/8.1.1 忘记对象类型

标签: 作者:易学笔记  更多资料请联系微信或QQ:1776565180

 

  • 易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态

  1. 如果 Instrument 为导出类类型,而不是基类类型,会发生什么事情呢?
  2. 这样会导致  “class Music”需要为每一个 tune(Instrument i) 编写方法,这样虽然行得通,但是对于每增加一个导出类,都需要新增一个tune(Instrument i) 方法,这样会带来巨大的工作量和麻烦
  3. 举例:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态

第8章 多态/8.2 转机/8.2.1 方法调用绑定

标签: 作者:易学笔记  更多资料请联系微信或QQ:1776565180

 

  1. 概念:指的是将一个方法调用和一个方法主体关联起来称为绑定
  2. 分类
    1. 前期绑定:
      1. 概念:由编译器和连接程序实现
      2. 举例:例如C语言
    2. 后期绑定
      1. 概念:在运行时根据对象类型进行绑定
      2. 举例:C++、Java
      3. Java中除了final与static方法外,所有都是后期绑定

第8章 多态/8.2 转机/8.2.2 产生正确的行为

标签: 作者:易学笔记  更多资料请联系微信或QQ:1776565180

 

    • 举例:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态
    • 动态绑定的例子
      1. 源代码:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态
        1. 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();
          		}
          	}
          
          }
          

           

        2. package mypackage.shape;
          
          import mypackage.Print;
          
          public class Shape {
          	public void draw() {
          		Print.print("Shape.dram");
          	}
          
          	public void erase() {
          		Print.print("Shape.erase");
          	}
          }
          

           

        3. package mypackage.shape;
          
          import static mypackage.Print.*;
          
          public class Circle extends Shape {
               public void draw() {
          		print("Circle.draw");
          	}
               public void erase() {
          		print("Circle.erase");
          	}
          }
          

           

        4. 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");
          	}
          }

           

        5. 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");
          	}
          }
          

           

      2. 输出结果:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态

第8章 多态/8.2 转机/8.2.3 可扩展性

标签: 作者:易学笔记  更多资料请联系微信或QQ:1776565180

 

  1. 参照: 第8章 多态/8.1 再论向上转型
  2. 这时候再往 易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态类中加入更多方法,同时导出类也添加通用的方法,没关系,易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态这个方法依旧可以使用,并且不用修改不用编译
  3. 扩展后的易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态类为:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态

第8章 多态/8.2 转机/8.2.4 覆盖私有方法

标签: 作者:易学笔记  更多资料请联系微信或QQ:1776565180

 

  1. 私有方法默认为final中,隐藏是不能覆盖的,如果在导出类中写相同名称的方法,是当做在导出类中新增的方法,而不是基类的方法
  2. 所以对于私有方法,在导出类中最好进行不同的命名

第8章 多态/8.2 转机/8.2.5 域与静态方法

标签: 作者:易学笔记  更多资料请联系微信或QQ:1776565180

 

    • 尽管域是public的,但是也不是多态的
    • 例子
      1. 源代码:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态
        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());
        	}
        
        }
        

         

      2. 输出结果:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态
  • 静态方法
  1. 尽管静态方法是public的,但是也不是多态的
  2. 例子
    1. 源代码:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态
    2. 输出结果:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态

第8章 多态/8.3 构造器和多态/8.3.1 构造器的调用顺序

标签: 作者:易学笔记  更多资料请联系微信或QQ:1776565180

 

  1. 导出类和基类调用顺序: 第7章 复用类/7.9 初始化以及类的加载/7.9.1 继承和初始化
  2. 组合、继承、多态性构造顺序例子
    1. 易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态源代码:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态
      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();
      	}
      
      }
      

       

    2. 输出结果:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态

第8章 多态/8.3 构造器和多态/8.3.2 继承和清理

标签: 作者:易学笔记  更多资料请联系微信或QQ:1776565180

 

  1. 通常使用dispose方法来清理,dispose调用顺序更好与对象引用声明顺序相反,参照: 第7章 复用类/7.4 结合使用组合和继承/7.4.1 确保正确清理
  2. 举例子:
    1. 源代码:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态
      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();
      	}
      
      }
      

       

    2. 结果输出:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态

第8章 多态/8.3 构造器和多态/8.3.3 构造器内部的多态方法的行为

标签: 作者:易学笔记  更多资料请联系微信或QQ:1776565180

 

    • 如果构造器中绑定了多态的方法,那将会发生什么事情呢?
    • 举例:
      1. 源代码:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态,因为调用顺序为:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态
        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);
        	}
        
        }
        

         

      2. 输出结果:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态
    • 结论
      1. 构造器应该足够简单,只进行初始化成员域即可,尽量不要调用方法
      2. 如果要调用方法也是调用final方法或者private方法,因为这些方法不会被覆盖

第8章 多态/8.4 协变返回类型

标签: 作者:易学笔记  更多资料请联系微信或QQ:1776565180

 

易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态


第8章 多态/8.5 用继承进行设计/8.5.1 纯继续与扩展

标签: 作者:易学笔记  更多资料请联系微信或QQ:1776565180

 

  1. 纯继承
    1. 概念:是一种is-a关系,指的是基类和导出类的方法一样多,也就是导出类没有新增方法
    2. 示意图:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态
  2. 扩展
    1. 概念:是一种“is-like-a”关系,指的是导出类在继承基类方法的基础上新增方法
    2. 示意图:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态
    3. 缺点:向上转型时基类不能访问这些方法

第8章 多态/8.5 用继承进行设计/8.5.2 向下转型与运行时类型识别

标签: 作者:易学笔记  更多资料请联系微信或QQ:1776565180

 

  1. 概念:指的是基类类型强制转换为导出类类型,这种转换时不安全的,因为基类类型不能保证能调用导出类方法
  2. 举例:易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态易学笔记--从0开始学JAVA(个人纯手工笔记共享 免费!免费!免费!)--第8章 多态

第8章 多态/8.6 总结

标签: 作者:易学笔记  更多资料请联系微信或QQ:1776565180

 

 

  1. 前期绑定还是后期绑定:第8章 多态/8.2 转机/8.2.1 方法调用绑定
    1. 对于C语言,没有方法重载,所以所有的C语言都是前期绑定的;
    2. 对于Java,除了final和static方法,都是动态绑定的
    3. 因为final方法只能在本类使用,static方法只能属性声明类或者导出类类名调用。
    4. 如果是向上转型对象调用static方法,那么调用的都是对象声明类型对应的方法(通常就是基类的方法)
  2. 域是不能多态的,也就是基类和导出类的域是分开存储的
  3. 如果多态发生在基类构造方法中,那调用的方法是导出类的,但是导出类的初始化在基类后面,那该方法有可能用了未初始化的变量,那是非常危险的