再贴个东东3.多态方法在构造函数中的行为
A.疑问:如果在构造函数中调用了一个动态绑定的方法,而这个方法又属于那个正在创建中的对象,那么它会产生什么效果?
答:则实际是根据动态绑定机制 调用 其派生类中覆写的方法。但是这个效果可能会出人意料,使程序产生一些潜伏的bug。注意,这时候派生类并未进行初始化!!!例如:如果该覆写方法访问了 派生类的数据成员时,它也不会被初始化。
a.分析:程序员会使用未初始化数据成员的派生类的覆盖方法吗?我想一般不会吧,我觉得覆盖方法很大程度就是要利用派生类自身的数据成员。所以我觉得基类的构造函数中调用派生类的覆盖方法是不被允许的行为!
b.如果构造函数实在需要调用方法,可以考虑在方法前加上final限定符(private也属于final),防止该方法被派生类覆盖.B.结论是:
一个好的构造函数应该是:
用最少的工作量把对象的状态设置好,而且尽可能的避免去调用方法。禁止调用非final的方法。

解决方案 »

  1.   

    我来大概解释一下super吧:单纯站在java的立场上,很难说说明问题,上面已经说得很清楚了。这里用C++的成员初始化列表解释:class Parent
    {
    public:
    1.    Parent() { }
    2.    Parent(int x) { }
    };class Child : public Parent
    {
    public:
    3.    Child() { }
    4.    Child(int x) : Parent(x) { }
    };通过3初始化child的时候,先要调用1,然后才3
    通过4初始化child的时候,先要调用2,然后才4实际上3.也等价于 
    5. Child() : Parent() {}这里的Parent()就是显式申明初始化Child的时候要调用Parent的那个无参构造函数(如果有的话)或者默认构造函数(如果没有无参构造函数)。其实这里的Parent()就相当于java的super(),这当然是可以省略的。
    而4则不同,Parent(x),就相当于super(x),通过它指明先调用2,这是没法省略的。总结一下,很简单,C++之所以用父类名去初始化对象属于父类的部分在于C++支持多重继承,用单一关键字无法确定到底初始化哪个父类;而java只支持单一继承,用super代替父类名作为一种简化;当然,简单地调用super()没有必要。