簡體   English   中英

這些訪問Java中其他類的方法之間有什么區別?

[英]What are the differences between these methods to access other classes in Java?

目前,我正在從事Java開發,並且正在努力理解實例和具有這種性質的事物的概念。 當我有一個變量或方法時,我需要在另一個類中訪問,目前

public class Class1 implements Listener {
private final Main main;
private final Class2 class2;

public Class1(Main main, Class2 class2) {
    this.main= main;
    this.class2 = class2;
}

我應該提到我正在嘗試開發一個Minecraft插件,因此Listener類必須實現Listener。 但是,當我嘗試為需要引用2個類的類注冊事件(同樣,這是Minecraft的另一件事)時,代碼變得混亂。 例如,要獲取引用另外2個其他類的類,則eventRegister可能如下所示:(在主類中)

  pm.registerEvents(new ClassX(this, new ClassY(this, new ClassZ(this))), this);

(注冊事件需要一個偵聽器和一個主類)

我的問題問:獲取另一個類並簡單地擴展它的方法之間有什么區別? 有區別嗎?

擴展類時,您將應用繼承。 您將可以從超類訪問所有public方法。

實現接口時,您要簽訂合同,必須從該接口實現所有非默認方法。

當您將一個實例傳遞到另一個實例(通過您的實例中的構造函數)時,您正在應用對象合成 ,這類似於說“我將把這台特定的引擎放入這輛特定的汽車”。 您可能希望將不同的引擎放入另一輛汽車,因此您將傳遞不同的引擎作為構造函數。

implements稱為繼承 繼承的思想是知道所有類都是同一類 例如,您可能會說“所有汽車都可以turnLeft()和turnRight()”,因此,如果有人想創建自己的汽車(或者在您的情況下,他們自己的插件),那么他們的汽車也需要能夠turnRight()turnLeft()

讓我們回到您的問題。 如果看到一段看起來“通用”的代碼,則可能需要將通用部分提取到其自己的類中,然后繼承該類。 例如,“所有動物都可以shout() ”或“所有工具都可以use() -d”。 但是,如果您想讓這只鴨子了解那只鴨子-您需要參考另一只鴨子中的一只鴨子。

但是,這並不意味着您需要使用構造函數。 構造函數用於對象不能沒有的引用(不能處於有效狀態)。 例如, new Duck(new DuckBrain())有意義,但是new Duck(new Duck())沒有意義。 對於這些情況,您可能會引入setter (在鏈接中搜索Java示例)。 設置器是更改對象包含內容的方法。

不必給類一個您需要的每件事的實例,而是給它一個存儲它們的對象。 在您的情況下,它可能是您插件的主類。

class ClassA implements Listener {

    private final MyPlugin plugin;

    public ClassA(MyPlugin plugin) {
        this.plugin = plugin;
    }
}

只要確保使用訪問修飾符或獲取器就可以從ClassA訪問MyPlugin中的所有內容。

您一直在做的事情是完全正常的,並且受到鼓勵。 沒有明確設計繼承的過度使用會導致錯誤的代碼。

您還通過構造函數傳遞了每個類的需求,這也是一種良好的實踐,稱為“依賴注入”,它有助於更​​好的測試和編寫單元測試。

對於高級項目,通常使用Dependency Injection框架來管理將您的依賴項傳遞到許多類中,但是對於小插件來說,則不必要。

根據這些類的可重用性,您可能希望為其創建一些接口。

如果使用依賴注入構造類變得很麻煩,那么您可以研究幾種模式來提供幫助。

工廠模式和構建器模式在整個行業中得到廣泛使用,這取決於構造的對象得到的頻率,復雜程度和變化程度。

創建的復雜對象通常很適合Factory模式

具有高可變性的簡單對象很適合構建器模式

如果通過構造函數傳遞所有內容變得困難,則始終可以在構造后初始化對象,但這會產生維護成本,因為您需要確保正確初始化了對象。

為什么您的class1需要引用class2? 它是對象還是OO編程中的某物,這意味着您的代碼將變得非常夫婦,這是一個糟糕的設計,您應該使用其他設計模式來使您的代碼解耦,即Class1不應依賴Class2。

回到您的問題,通過構造函數傳遞對象與擴展傳遞對象有什么區別?

當您擴展一個類時,您可以覆蓋母類中的某些方法,即Dog extends Animal或者甚至可以在您的超類中調用該方法(通過super.method()的Animal類)。

在這種情況下,當您通過構造函數傳遞對象時,可以在通過構造函數傳遞的對象中使用該對象。

減少代碼混亂的最好方法是我建議使用偵聽器模式(pub子程序),例如https://github.com/greenrobot/EventBus之類的現有庫,您可以在其中創建事件,例如可以在播放器中創建事件如果您創建了另一個訂閱該事件的類,那么當事件發生時,它將通知所有訂閱者觸發一個函數。 現在,您無需將所有類都耦合在一起。

暫無
暫無

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

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