【问题标题】:Getting current object properties when calling an undeclared super method from abstract class从抽象类调用未声明的超级方法时获取当前对象属性
【发布时间】:2013-01-14 20:34:26
【问题描述】:

可能是一个非常基本的 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 上下文属性。

Config.java

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}

【问题讨论】:

    标签: java inheritance


    【解决方案1】:

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

    对于那个特定的例子,我将使用一个专用的构造函数(我已对其进行保护以防止客户端类访问它):

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

    【讨论】:

    • 感谢您的回答!!其实比较复杂,A有很多标准的属性,那些不是通过特定的方式得到的,一个外部对象被传递给那些方法,而这些属性是和这个外部对象一起使用的,所以要做的就是这么多的属性那样。更具体地说,我正在传递一个 servlet 上下文,并且我正在为每个超类设置属性,所以我想在那里声明方法,并在扩展类中具有不同的配置。
    • 也许向我们展示您是如何设置和检索其中一个属性的,以便更清晰?
    • @JuanGarcia 我能想到的替代方案是:(i)使所有变量受保护 - 这样您就可以从子类访问和修改它们(ii)将设置器添加到父类并使用它们修改子类中的变量 (iii) 使用构建器模式:创建一个 ConfigBuilder 类来保存变量并让您的子类以他们想要的方式填充 ConfigBuilder。
    • @JuanGarcia 我添加了一个包含配置的附加类的示例。
    • 谢谢。正如您所建议的,我在超类中使用了受保护的属性。对于扩展类,我只是在构造函数中分配属性值。如果有人觉得有用,我已经写了自己的答案。 @assylias +1 为您提供帮助。
    【解决方案2】:

    为此: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”

    【讨论】:

      【解决方案3】:

      我只是想出了一个简单的方法来使用构造函数并将超类属性更改为受保护(感谢@assylias 的回答): 配置.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";
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-12
        • 2016-05-10
        • 2021-06-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多