关于多态

以下摘自《Java编程思想》

       在面向对象的程序设计语言中,多态是继续数据抽象和继承之后的第三种基本特征。

多态通过分离做什么和怎么做,从另一角度将接口和实现分离开来。多态不但能够改善代码的组织结构和可读性,还能够创建可扩展的程序---即无论在项目最初创建时还是在需要添加新功能时都可以“生长”的程序。多态也被称作动态绑定,后期绑定或运行时绑定。

java中除了static方法和final防止(private方法属于final方法)之外,其他所有的方法都是后期绑定。


1、域与静态方法

public class Super {
	
	public int field = 0;
	public int getField (){
		return field;
	}

}
public 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="+sup.field+"-sup.getField()="+sup.getField());
		Sub sub = new Sub();
		System.out.println("sub.field="+sub.field+"-sub.getField()="+sub.getField()+"--sub.getSuperField="+sub.getSuperField());
	}

}

output:

sup.field=0-sup.getField()=1
sub.field=1-sub.getField()=1--sub.getSuperField=0

当sub对象转型为super引用时,任何域访问操作都将由编译器解析,因此不是多态的。在本例中,为Super.field和Sub.field分配了不同的存储空间。这样,Sub实际上包含了两个成为field的域。


如果某个方法是静态的,它的行为就不具有多态性:

public class StaticSuper {
	
	public static String staticGet(){
		return "Base staticGet()";
	}
	
	public String dynamicGet(){
		return "Base dynamicGet()";
	}

}

public class StaticSub extends StaticSuper {
	public static String staticGet() {
		return "Dervied staticGet()";
	}

	public String dynamicGet() {
		return "Dervied dynamicGet()";
	}
}

public class StaticPolymorphism {

	public static void main(String[] args) {
		
		StaticSuper sup = new StaticSub();
		System.out.println(sup.staticGet());
		System.out.println(sup.dynamicGet());

	}

}

静态方法是与类,而并非单个的对象相关联的。


2、构造器多态

构造器不具有多态性(她们实际上市static方法只不过该static声明是隐式的)。

public class Glyph {
	void draw(){
		System.out.println("Glyph.draw()");
	}
	
	Glyph(){
		System.out.println("Glyph() before draw()");
		draw();
		System.out.println("Glyph() after draw()");
	}

}

public 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);
		
	}
}

output:

Glyph() before draw()
RoundGlyph.draw(), radius=0
Glyph() after draw()
RoundGlyph.RoundGlyph(),radius=5

初始化顺序如下:

1、在其他任何事物发生之前,将分配给对象的存储空间初始化成二进制的零。

2、如前所述那样调用基类构造器,此时,调用被覆盖后的draw()方法,(要在调用RoundGlyph构造器之前调用),由于步骤1的原因,radius的值为0

3、按照声明的顺序调用成员的初始化方法。

4、调用导出类的构造器主体。


因此,编写构造器时有一条有效的准则,用尽可能简单的方法使对象进入正常状态,如果可以的话,避免调用其他方法。


你可能感兴趣的:(关于多态)