1

可能是一个非常基本的java问题。

我有一个抽象类,简化它:

public abstract class A{
  private String value = "A" ; // I want it undeclared, but set it for testing purpouse

  public String getValue(){
    return value ;
  }
}

然后我有一个扩展它的类:

public abstract class B{
  private String value = "B" ;
}

所以我遇到的问题是,当通过类 A 创建 B 的实例并调用 getValue() 时,它总是返回“A”:

A b = new B();
b.getValue(); // returns "A"

如何让 B 使用他自己的属性调用超级方法而无需复制代码?A 它目前太长了,它被扩展到许多不同的类,它们的不同之处仅在于它的属性值,并且它们都使用与超类相同的方法。

谢谢!

编辑:

对不起,我没有那么具体。我有很多属性,以及一些处理这些属性的方法。扩展类更改了这些属性,但我想将超级方法与扩展类实例对象一起使用,而不必两次声明它们。如果有帮助,我正在使用 servlet 上下文属性。

配置文件

public abstract class Config {
    private String someValue1 ;
    ...
    private String someValuen ;

    public void export(ServletContext cxt){
        cxt.setAttribute("someValue1", someValue1);
        ...
        cxt.setAttribute("someValuen", someValuen);
    }
}

SomeConfig.java

public class SomeConfig {
    private String someValue1 = "something" ;
    ...
    private String someValuen = "something else" ;
}

SomeServlet.java

ServletContext cxt = getServletContext() ;
Config config = new SomeConfig();
config.export(cxt);

为了清楚起见,属性都有不同的名称。我将它们从 jsp 中用作: ${someValuen}

4

3 回答 3

5

它不起作用的原因是只能覆盖方法 - 变量成员被隐藏(如果您value从 B 类打印,它将是"B")。

对于该特定示例,我将使用专用的构造函数(我已将其设置为 protected 以防止客户端类访问它):

public abstract class A {
    private final String value;

    public A() { //for internal / testing use only
        value = "A";
    }

    protected A(String value) {
        this.value = value;
    }

    public String getValue(){
        return value ;
    }
}

然后 B 可以简单地调用相关的构造函数:

public class B extends A {
    public B() {
        super("B");
    }
}

编辑

示例ConfigHolder

public class ConfigHolder {

    String value1;
    String value2;
    String value3;

    public ConfigHolder value1(String value1) {
        this.value1 = value1;
        return this;
    }
    //same for other variables
}

然后在A类:

public abstract class A {
    private final ConfigHolder config;

    public A() { 
        this.config = new ConfigHolder()
                 .value1("value1")
                 .value2("value2");
    }

    protected A(ConfigHolder config) { 
        this.config = config;
    }

    public void export(ServletContext cxt){
        cxt.setAttribute("someValue1", builder.value1);
        ...
        cxt.setAttribute("someValuen", builder.valuen);
    }
}

在 B 中:

public class B extends A {
    public B() {
        super(new ConfigBuilder()
                   .value1("value1InB")
                   .value2("value2InB"));
    }
}
于 2013-01-14T11:34:40.773 回答
0

为此:A b = new B();B 必须是 A 的子类

此外,抽象类不能被实例化,即不能创建抽象类对象。如果您尝试这样做,编译器将产生错误。

public abstract class A{
  private String value = "A" ;

  public String getValue(){
    return value ;
  }
}


public class B extends A{
    private String value ;
    public B(){
        value = "B";
    }
}

现在你可以做B notAbstractClass = new B();

并且在这样做notAbstractClass.getValue();时必须返回“B”

于 2013-01-14T12:08:58.660 回答
0

我只是想出了一个简单的方法来使用构造函数并将超类属性更改为受保护(感谢@assylias 回答):Config.java

public abstract class Config {
    protected String someValue1 ;
    ...
    protected String someValuen ;

    public void export(ServletContext cxt){
        cxt.setAttribute("someValue1", someValue1);
        ...
        cxt.setAttribute("someValuen", someValuen);
    }
}

SomeConfig.java

public class SomeConfig {
  public SomeConfig(){
    someValue1 = "something";
    ...
    someValuen = "something else";
  }
}
于 2013-01-14T12:21:33.803 回答