簡體   English   中英

Java包裝器:覆蓋超級構造函數中調用的方法

[英]Java wrapper: overriding a method called in the super constructor

我想用Java包裝一個類,但問題如下:

public class A {

    public A() {
       doSomething();
    }

    public void doSomething() {
    }

}

現在,當我嘗試包裝此類並將所有方法委托給包裝器時

public class Wrapper extends A {

   private final A a;

   public Wrapper(A a) {
      super();
      this.a = a;
   }

   @Override
   public void doSomething() {
      this.a.doSomeThing();
   }


}

當然我得到一個NPE因為'a'仍然是null,因為它是在調用overriden doSomething()方法的super()調用之后設置的。 這個問題有什么解決方案嗎? 我想到的唯一一件事就是制作一個工廠方法並設置一個靜態變量來保存對a的引用,但這對我來說似乎很難看。

我建議更改代碼,以便在構造函數中不調用doSomething。

或者將A拆分為接口,實現Wrapper實現接口,不從A繼承

public interface IA {

    public void doSomething() {
    }

}
public class A implements IA {

    public A() {
       doSomething();
    }

    public void doSomething() {
    }

}


public class Wrapper implements IA {

   private final IA a;

   public Wrapper(IA a) {
      this.a = a;
      doSomething();
   }

   @Override
   public void doSomething() {
      a.doSomeThing();
   }
}

以這種方式更改您的包裝器。 您不需要明確地持有A. 表達式super與您提交的相同:

class Wrapper extends A {

    public Wrapper() {
    }

    @Override public void doSomething() {
        super.doSomething();
    }
}

或以其他方式提取接口並更改您的代碼,如下所示:

class Wrapper implements AA {

    private final AA child;

    public Wrapper(AA child) {
        this.child = child;
    }

    @Override public void doSomething() {
        child.doSomething();
    }
}

class A implements AA {

    public A() {
       doSomething();
    }

    @Override public void doSomething() {}
}

interface AA {
    public void doSomething();
}

避免這種情況的一種方法是通過從基類公開init方法(或任何其他名稱)(如果您控制其邏輯)。 然后將調用從構造函數移動到init方法:

public class A {

    public A() {
    }

    public void init() {
        doSomething();
    }

    public void doSomething() {
    }
}

在創建類的實例之后,您應該更新代碼以調用init方法,這可能是一些樣板:

A instance = new Wrapper();
instance.init();

而不僅僅是

A instance = new Wrapper();

如果使用Spring和DI,則可以在xml上下文中指定init-method ,因此Spring會在解析依賴項時為您調用它。

如果doSomething方法是公共的 ,並且不接受任何參數,則可以在代碼和Spring中直接使用它而不是init方法。

通常,由於遇到的問題,在構造函數中使用可覆蓋的方法是反模式。 無法預測派生類如何覆蓋方法,如果它們依賴於非初始化資源,那么您就遇到了麻煩。

兩個小小的變化,你需要的年輕人

 public class Wrapper extends A {

       private final A a;

       public Wrapper(A a) {
          super();
          this.a = a;

        //this will execute method doSomething wrom Wrapper class after variable a is set
          doSomething(); 

       }

       @Override
       public void doSomething() {
    //this will prevent to call metod from superclass constructor, bit risky thou
         if (a!=null)       
          this.a.doSomething();
       }
    }

但是在constructo中調用的重寫方法通常是不好的做法,並且聞起來很糟糕

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM