Java中的抽象方法即使被覆盖也可以具有默认行为吗?

时间:2019-02-11 14:31:37

标签: java

也许这种方法是错误的。我的想法如下:

public abstract AbstractParser<T extends Value> {
  T value;

  //want to do something like
  public abstract void parseSomething(Model model) {
    value = (T) model.getValue()
  }
}

然后我希望每个子类都重写parseSomething而不丢失该默认行为。因此,当子项覆盖parseSomething时,它将具有 value 的正确实现。

public ConcreteParser extends AbstractParser<ConcreteValue> {
  //now in Value I have a ConcreteValue to access

  @Override
  public void parseSomething(Model model) {
    //here I want to do stuff with value without having to do:
    value = (ConcreteValue) model.getValue();
    //in every implementation I create
  }
}

有什么想法吗?

4 个答案:

答案 0 :(得分:1)

缺少的第一个,您需要Class<T>才能强制转换为T(类型擦除)。 (如果模型不可参数化。)

对于这个问题,有一个很好的解决方案,

  • 最终的,不可覆盖的公共API service 方法-parseSomething;
  • 内部受保护的 request 实现方法,应该被覆盖-onParseSomething。

可覆盖的方法在最终的public方法中被调用,并且可以具有更多的参数,例如value。该方法可以是abstract

所以:

public abstract AbstractParser<T extends Value> {
  private final Class<T> valueType;
  protected T value;

  protected AbstractParser(Class<T> valueType) {
    this.valueType = valueType;
  }

  // Class users will call this method
  public final void parseSomething(Model model) {
    value = valueType.cast(model.getValue());
    onParseSomething(model, value);
  }

  // Class implementors will override/implement this method
  protected void onParseSomething(Model model, T value) {
  }
}


public ConcreteParser extends AbstractParser<ConcreteValue> {

  public ConcreteParser() {
      super(ConcreteValue.class);
  }

  @Override
  public void onParseSomething(Model model, ConcreteValue value) {
  }
}

答案 1 :(得分:0)

是的,甚至从Java 8开始扩展到接口:

public interface IExample {

    default public String test() {
        return " world!";
    }

}

public class Example implements IExample {

    @Override
    public String test() {
        return "Hello " + IExample.super.test();
    }

}

要引用父接口的超级方法,还必须在super之前包括类名称。最终结果:

System.out.println(new Example().test());
//Hello world!

从语义上讲,如果您想保护特定父方法的功能,并且让子类仅定义行为的一个子集,请考虑使用面向公众的方法,以及用于定义行为子集的受保护方法:

public abstract class AbstractParser<T extends Value> {

    protected T value;

    //final, cannot be overridden
    public final void parseSomething(Model model) {
        this.value = (T) model.getValue();
        this.continueParsing();
    }

    protected abstract void continueParsing();

}

public class ConcreteParser extends AbstractParser<ConcreteValue> {
    @Override
    protected void continueParsing() {
        //invoked after the value `T` is set by the public method
        //references to `this.value` will be of type `T` or in this case, `ConcreteValue`
    }
}

答案 2 :(得分:0)

您要查找的内容只能通过泛型来实现。

可以Model类进行参数化:

class Model<T> {
   ...
   T getValue();
   ...
}

然后AbstractParser类可以重写为:

abstract class AbstractParser<T> {
   T value;

   public abstract void parseSomething(final Model<T> model) {
      this.value = model.getValue();
   }
}

由于在使用前已初始化value的保证,因此可以通过构造函数注入将类重写为不可变的。

abstract class AbstractParser<T> {
   final T value;

   AbstractParser(final Model<T> model) {
      this.value = model.getValue();
   }

   ...
}

答案 3 :(得分:0)

这将为您做到:

public ConcreteParser extends AbstractParser<ConcreteValue> {

 @Override
 public void parseSomething(Model model) {
   if(!(model instanceOf ConcreteValue)) // to ensure safety
      return;
   //do what ever you like first, this.value is null by far if 
   //this method is getting called the 1st time

   super.parseSomething(model);

   // now you can use value as you like from here on. 
 }
}