【问题标题】:Overriding Abstract Fields Java覆盖抽象字段 Java
【发布时间】:2015-08-25 20:38:18
【问题描述】:

我有一个抽象类,它有一个由所有扩展该类的类使用的方法。该方法对于每个类都是相同的,所以我不想在这些类中一遍又一遍地编写它。问题是该方法使用在每个类中声明的 2 个变量。如果没有抽象类中的这些变量,我就无法在抽象类中使用该方法。但如果我这样做,它们将采用抽象类中指定的值,而不是扩展它的类。我该如何解决这个问题?

示例代码:

public abstract class Example {
   public String property1 = ""
   public String property2 = ""
    public ArrayList<String> getPropertyies() {
        ArrayList<String> propertyList = new ArrayList<>();
        propertyList.add(property1);
        propertyList.add(property2);
        return property1;
    }
}

public class ExampleExtension extends Example {
    public String property1 = "this is the property";
    public String property2 = "this is the second property";
}

【问题讨论】:

  • 什么是 Java "abstract field"
  • 这是一个非常糟糕的编码模式。任何好的 IDE 都会告诉你 ExampleExtension.property1hiding Example.property1。如果您讨厌阅读您的代码的人,请坚持下去,包括。自己。
  • 同样的评论可以说得很好。请以尊重和正直的态度发表评论。

标签: java oop abstract-class encapsulation


【解决方案1】:

您应该在抽象类中将字段的范围限制为private,并声明一个构造函数来填充值:

public abstract class Example {
    private final String property1;
    private final String property2;

    protected Example(String property1, String property2) {
        this.property1 = property1;
        this.property2 = property2;
    }
    //...
}

然后子类将通过调用 super 构造函数来初始化其构造函数中的字段值:

public class ExampleExtension extends Example {

    public ExampleExtension() {
        super("value1", "value2");
        // initialize private fields of ExampleExtension, if any
    }
    // ...
}

【讨论】:

  • 为什么要初始化Examplesuper("value1", "value2");)的property1和property2? ExampleExtension 是否有这些字段,它们的值是什么?
  • ExampleExtension“拥有”这些字段,因为它扩展了Example。但由于private 可见性,它没有直接的读/写访问权限。如果需要从扩展类中读取字段的值,可以在超类中为它们添加一个getter。
  • 谢谢!是的,这些私有字段必须在构造函数中初始化。因为它们在ExampleExtension中没有再次定义,所以它们存在于Example中,可以用getter访问。
【解决方案2】:

您不必覆盖变量。您可以在构造函数中设置属性的初始值:

public class ExampleExtension extends Example {

    public ExampleExtension() {
        property1 = "this is the property";
        property2 = "this is the second property";
    }

}

更好的方法是使用带参数的构造函数,正如 Mick Mnemonic 在另一个答案中所建议的那样。

【讨论】:

    【解决方案3】:

    IMO Mick 的解决方案是最实用的,但请注意,您也可以选择将属性抽象化,然后使用子类多态性来要求子类覆盖属性实现:

    public abstract class Example {
       public abstract String getProperty1();
       public abstract String getProperty2();
    
        public ArrayList<String> getPropertyies() {
            ArrayList<String> propertyList = new ArrayList<>();
            propertyList.add(getProperty1());
            propertyList.add(getProperty2());
            return propertyList;
        }
    }
    
    public class ExampleExtension extends Example {
        public String getProperty1() { return "this is the property"};
        public String getProperty2() { return "this is the second property"};
    }
    

    【讨论】:

    • abstract String时会报错:“Modifier 'abstract' not allowed here”。
    【解决方案4】:

    在这种情况下创建不同的(例如property1,property2)抽象方法。搜索模板模式的相关阅读

    public abstract class Example {
           public ArrayList<String> getPropertyies() {
            ArrayList<String> propertyList = new ArrayList<>();
            propertyList.add(getProperty1());
            propertyList.add(getProperty2());
            return property1;
        }
    
        public abstract getProperty1();//overriden by other class that has diff value for property1
        public abstract getProperty2();//overriden by other class that has diff value for property2
    }
    

    【讨论】:

      猜你喜欢
      • 2013-02-25
      • 1970-01-01
      • 1970-01-01
      • 2012-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多