第八章:多态

向上转型

  • 向上转型:把对某个对象的引用视为对其基类型的引用的做法被称作为向上转型

  • 后期绑定:在运行时根据对象的类型进行绑定,也叫作动态绑定或者运行时绑定;在Java中除了staticfinal方法(private也属于final方法)之外,其它所有的方法都是后期绑定;Java中所有的方法都可以通过后期绑定实现多态

  • 只有非private方法才可以被覆盖(重写),但是还是要密切注意覆盖private方法的现象,这时虽然编译器不会报错,但是也不会按照我们所期望的来执行。确切的说,在导出类中,对于基类中的private方法,最好采用不同的名字

缺陷:域与静态方法

  • 任何域的访问操作都将由编译器解析,因此不是多态的

    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){
            Super sup = new Sub();
            System.out.println(sup.field); //0
            System.out.println(sup.getField()); //1
            
            Sub sub = new Sub();
            System.out.println(sub.field); //1
            System.out.println(sub.getField()); //1
            System.out.println(sub.getSuperField()); //0
        }
    }
    
  • 如果某个方法时静态的,它的行为就不具有多态性;静态方法是与类绑定,而并非与单个的对象相关联的

    class StaticSuper{
        public static String staticGet(){
            return "Base staticGet";
        }
        
        public String dynamicGet(){
            return "Base dynamicGet";
        }
    }
    
    class StaticSub extends StaticSuper{
        public static String staticGet(){
            return "Derived staticGet";
        }
        
        public String dynamicGet(){
            return "Derived dynamicGet";
        }
    }
    
    public class StaticMethod{
        public static void main(String[] args){
            StaticSuper sup = new StaticSub();
            System.out.println(sup.staticGet()); //Base staticGet
            System.out.println(sup.dynamicGet()); //Derived dynamicGet
        }
    }
    

构造器和多态

  • 通常构造器不同于其它种类方法,涉及到多态仍是如此;尽管构造器并不具有多态性(实际上是static方法,只不过static声明是隐式的),但还是非常有必要理解构造器怎样通过多态在复杂的层次结构中运作

  • 基类的构造器总是在导出类的构造过程中被调用,而且按照继承层次逐渐向上链接,以使每个基类的构造器都能得到调用

  • 复杂对象调用构造器的顺序:调用基类的构造器按照声明顺序调用成员的初始化方法调用导出类构造器的主体

  • 在构造器内唯一能够安全调用的那些方法是基类中的final方法或private方法,这些方法不能被覆盖,不会出现在父类中调用子类重写的方法,而此时子类还没有初始化的问题

    class Glyph{
        void draw(){
            System.out.println("Glyph.draw()");
        }
        
        Glyph(){
            System.out.println("Glyph() before draw()");
            draw();
            System.out.println("Glyph() after draw()");
        }
    }
    
    class RoundGlyph extends Glyph{
        private int radius = 1;
        
        RoundGlyph(int r){
            radius = r;
            System.out.println("RoundGlyph.RoundGlyph(), radius = "+radius);
        }
        
        void draw(){
            System.out.println("RoundGlyph.draw(), radius = "+radius)
        }
    }
    
    public class PolyConstructors{
        public static void main(String[] args){
            new RoundGlyph(5);
            //Glyph() before draw()
            //RoundGlyph.draw(), radius = 0
            //Glyph() after draw()
            //RoundGlyph.RoundGlyph(), radius = 5
        }
    }
    

你可能感兴趣的:(第八章:多态)