[英]Can an abstract method in Java have a default behavior even if it is overridden?
也許方法是錯誤的。 我的想法如下:
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 時,它將具有正確實現它的價值。
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
}
}
有任何想法嗎?
缺少的第一個,您需要一個Class<T>
來轉換為T
(類型擦除)。 (如果模型不可參數化。)
對於這個問題有一個很好的解決方案,與
parseSomething
、公共 API服務方法 - parseSomething
; 可覆蓋的方法在最終的公共方法中被調用,並且可以有更多的參數,比如值。 該方法可以是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) {
}
}
是的,這甚至擴展到 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 方法,還必須在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`
}
}
您正在尋找的內容只能通過泛型來完成。
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();
}
...
}
這將為您做到:
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.
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.