简述
多态是继封装、继承之后的第三个基本特征在面向对象设计的语言当中。封装实现了数据私有化,继承实现了代码的复用,多态可以让我们的代码更具可读性且尽可能的消除对象之间的耦合关系。多态就是多种状态,一个类型不仅可以表现出它自己类型的特征,如果有明显的继承(extend)那么它也可以表现出父类(基类)的特征。
详解多态
其实实现多态最底层就是编译器的静态编译和动态编译(运行时编译)。所谓静态编译就是在程序运行前将方法的调用和方法的主体链接起来。动态编译则可以理解为当程序运行时动态的分析和绑定被调用的方法体。接下来我们看个栗子~
public class Rodent {
public void eat() {
System.out.println("Rodent is eatting");
}
public static void main(String[] args) {
Rodent rodent = new Rodent();
Rodent mouse = new Mouse();
Rodent gerbil = new Gerbil();
rodent.eat();
mouse.eat();
gerbil.eat();
}
}
class Mouse extends Rodent {
public void eat() {
System.out.println("Mouse is eatting");
}
}
class Gerbil extends Rodent {
public void eat() {
System.out.println("Gerbil is eatting");
}
}
多态虽然会比较方便,但是同时也有两个缺陷一个就是覆盖父类私有方法另一个是域和静态方法的多态调用。
同样的我们再看个例子:
public class Rodent {
public int averageWeight = 1;
public int getAverageWeight() {
return this.averageWeight;
}
private int getSuperAverageWeight() {
return super.averageWeight;
}
public static void main(String[] args) {
Rodent rodent = new Rodent();
Rodent mouse = new Mouse();
System.out.println(rodent.averageWeight);
System.out.println(rodent.getAverageWeight());
System.out.println(mouse.averageWeight);
System.out.println(mouse.getAverageWeight());
System.out.println(mouse.getSuperAverageWeight());
}
}
class Mouse extends Rodent {
public int averageWeight = 1;
public int getAverageWeight() {
return this.averageWeight;
}
public int getSuperAverageWeight() {
return super.averageWeight;
}
}
除了上述的两个缺陷,另外一个就是类中的static方法同样是不具备多态性的,因为static的东西是和类绑定在一起的
。
这些在笔试中很容易中招!!
多态状态下的初始化过程
废话不多说先上
栗
子:
Class Glyph {
void draw() {
System.out.println("Glyph.draw()");
}
Glyph() {
System.out.println("Glyph before draw()");
this.draw();
System.out.println("Glyph after draw()");
}
}
Class RoundGlyph extends Glyph {
private int radius = 1;
RoundGlyph(int radius) {
this.radius = radius;
System.out.println("RoundGlyph.RoundGlyph() radius = " + radius);
}
void draw() {
System.out.println("RoundGlyph.draw() radius = " + radius);
}
}
根据结果来解析一下初始化的具体步骤:
1. 在对象刚刚分配存储空间时,所有的存储空间会被暂时的初始化为二进制的0。
2. 在调用子类的构造方法时会先去向上寻找,在父类过程中有个很有趣的调用。首先因为构造方法是默认static的也就
是说是跟类型绑定的,那么在构造方法中如果调用了动态的方法时,它会实现多态,又因为步骤1,才导致了最初的
radius=0的结果。
3. 按照声明的顺序调用成员变量的初始化方法。
4. 调用子类的构造方法体。
结论
多态虽然是有很多好处,但是它却是基于继承这个条件实现的。所以在我们编写程序设计系统的时候,相对于继承,更好的办法是组合。其次还有一个问题就是多态可能会导致子类信息丢失的问题,也应当注意。