2017-05-09 85 views
1

我工作的一個對象層次結構是這樣的:匕首2子類具有比父類更具體的依賴

class Foo extends View 
{ 
    @Inject BaseDependency dep; 

    Foo() // Default android view constructors 
    { 
     injectDependencies(); 
    } 

    protected void injectDependencies() 
    { 
     getApp().getFooComponent().inject(this); 
    } 
} 


class ExtraBaseDependency extends BaseDependency 
{ 
    @Inject 
    ExtraBaseDependency() {} 
} 

class Bar extends Foo 
{ 
    @Inject ExtraBaseDependency dep; 

    @Override 
    protected void injectDependencies() 
    { 
     getApp().getBarComponent().inject(this); 
    } 
} 

我試圖解決的問題是,我想在我的更具體的「 Bar'使用更多方法子類化'ExtraBaseDependency',並且我還想爲Foo提供與從Bar中使用的整個層次結構中收集數據相同的對象。

我認爲,通過重寫injectDependencies()而不是調用super,我可以提供我的子類和它的父類他們需要的依賴關係,但只有其中的一個可以共享,但Bar會得到更具體的接口因此它可以完成它的工作。

我看到的行爲是,雖然它編譯和運行,我看到ExtraBaseDependency被構造兩次。

我的FooComponent和BarComponents具有不同的作用域和不同的模塊,它們都是獨立的。我不確定爲什麼我沒有在子類中獲得基類中的相同實例。

回答

2

你的兩個領域都將繼續存在; fields are not polymorphic in Java。 Foo無法訪問Bar.dep,但Bar可以通過super.dep訪問Foo.dep

匕首將自動注入超領域和你注入任何類型的方法, 因此,如果調用inject(Bar)匕首將注入Foo的領域以及酒吧的。 (每a note about covariance,你必須要小心,不要打電話給inject(Foo),因爲這隻會注入Foo的領域,即使你在一個酒吧實例傳遞在運行時See more here, but injecting without explicitly calling super is the right thing to do anyway.。)

幾個解決方案:

  • 讓它成爲。 Foo需要一個BaseDependency,Bar需要一個ExtraBaseDependency,而且Foo甚至可以保持該依賴包-private,因此Bar無法訪問Foo的字段(如果該字段是有狀態的或者涉及多個線程,則該字段可能很重要)。如果你認爲每個類負責聲明自己的依賴關係,那麼這是按照預期工作的,儘管浪費了。

  • 如果應該限定範圍,則依賴項的範圍。如果BaseDependency和ExtraBaseDependency是在其組件的生命週期相一致,你可以用一個範圍(例如@Singleton@Reusable)以減少依賴娛樂,或者只是保存在@Module返回一個實例,如果它是比較合適的標記它自己管理單例實例。這不是一個很好的通用解決方案,但是如果這是一直拖延的工作,那麼你也可以用它解決這個問題。

  • 如果可能的話切換到構造函數參數(它不是,你的情況)。如果Bar擴展Foo,Bar可以有一個@Inject -annotated構造函數,該函數顯式調用Foo的構造函數,並使用您請求的特定依賴項。當然,對於Android視圖,您需要註冊成員;這是您的其他案例或其他讀者的選項。

  • 從Foo.dep中刪除@Inject註釋。 Foo。DEP的注入顯然取決於它的子類,字段不是多態的,所以讓富簡單地聲明其@Inject -annotated場是不是你正在使用它的方式是安全的。

  • 重構的Foo成抽象基類。這也不是適用於所有的通用的解決方案,但你可以通過設計爲富子類和暴露BasicFoo或DefaultFoo執行清理類層次結構的困境。這將使得填充Foo.dep成爲子類的責任,無論如何,這可能更容易在您的類層次結構中推理。

+0

我很欣賞的評論。我沒有嘗試過抽象類,但我覺得這應該可以工作。 我不能保持它的方式,因爲依賴是一個'中介'類型的對象,並且需要對類及其所有超類都一樣。 依賴項的作用域是自定義作用域。 如果我從基類中刪除@Inject,它將如何獲得它的依賴關係? 我還沒有試過讓這個類成爲一個基類,但這可能工作。我需要進一步研究。你會爲BaseDependency獲得一個抽象的getter嗎? – Stampede10343

+0

通過MembersInjectors挖掘,看起來Dagger選擇使用兩個不同的提供者來注入Foo和Bar。看起來抽象類可能是唯一的出路。 – Stampede10343