0

我有一个基类 A,有一个从 A 的构造函数调用的方法“say”。所有可继承的类都像它一样使用方法“say”。但是其中一个类需要重新定义这个方法。这怎么可能?

当然,我可以将基本方法“say”表示为抽象方法,但这样,我必须在所有可继承的类中复制相同的方法“say”。

如果我只是重新定义方法而不将基数表示为抽象,则不会调用它。

public abstract class A(){
     public A(){
        say();  //  <- wanna call this method from heritable class, if its redefined. 
     }
     protected void say(){};
}

public class B extends A(){
     public B(){
        super();
     }
     private void say(){};
}

重构 1

public abstract class A(){
     public A(){
       //  constructor methods             
     }
     protected void say(){};
     protected void executeSay(){
       say();
     }
}

public class B extends A(){
     public B(){
        super();
        executeSay();
     }
     @Override
     protected void say(){};
}
4

4 回答 4

11

首先必须明确一点:从构造函数调用可覆盖的方法是众所周知的反模式。它几乎肯定会破坏您的代码,因为子类方法将在子类构造函数完成之前被调用,因此会观察到一个未初始化的对象。因此,我最好不要向您提供有关实现此反模式所涉及的 Java 技术细节的详细建议。

满足您的要求的唯一安全方法是让构造完成,然后才调用一种initialize方法。如果要确保initialize始终调用,请将构造函数设为非公开并提供工厂方法。

不幸的是,Java 需要您进行大量工作才能使其正常工作。

于 2013-05-15T07:05:29.253 回答
4

您不能实例化抽象类。也就是说,您必须将抽象类引用链接到具体的继承类。例如。A a = 新 B(); 如果是这种情况,并且 B 重新定义了 say() 方法,那么 B 中的 say 方法将被调用。

public class TestPad {
    public static void main(String[] args) {
        A a = new B();
    }
}
abstract class A {
    public A() {
    say();
    }
    public void say(){
    System.out.println("A");
    };
}

class B extends A {
    public B() {
    super();
    }
    public void say() {
    System.out.println("B");
    }
}

输出将是 B

于 2013-05-15T07:16:28.023 回答
3
public class B extends A {
    public B() {
        super();
    }

    @Override
    protected void say() {
        // your diffent say code
    };
}

我不确定您是否可以减少对私人的可见性。

于 2013-05-15T07:04:41.210 回答
0

由于多态方法调用,在您的情况下,如果您覆盖它,将调用 B.say()。

但正如@sanbhat 评论的那样,您需要更改 to 的可见say()protected

于 2013-05-15T07:05:04.523 回答