簡體   English   中英

外部訪問內部私有類字段的 Java 最佳實踐

[英]Java best practice for outside access to inner private class fields

我搜索了很多我的問題的答案並找到了幾個選項,想知道你這是最佳實踐。

用例:所以我有一個單例類AccontManager ,它有一個只與它相關的內部類,它是一個User類。

public class AccontManager {

private static final AccountManger ourInstance = new AccountManger();
private User user;

public static AccountManger getInstance()
{
    return ourInstance;
}

private AccountManger(){}

public User getUser(){
    return this.user;
}

private class User{
    private String id;
    
    private User (String id){
        this.id = id;
    }
}
}

現在,情況是User字段必須訪問外部包類,但用戶類只對這個單例類是唯一的,因此內部類必須是私有的。

最佳情況下,在內部類中創建公共 getter 方法來獲取用戶字段是最好的,但是由於內部類是私有的,所以這是不可能的。

可能的做法:

  1. 實踐:在外部AccountManager類中為User字段創建相應的 getter 方法。

    缺點:用戶字段與User相關,因此外部類不應為其字段提供 getter 方法。

    代碼示例

     public class AccountManger { private static final AccountManger ourInstance = new AccountManger(); private User user; public static AccountManger getInstance() { return ourInstance; } private AccountManger(){} public User getUser(){ return this.user; } public String getUserId() // <-- get User id { return user.id; } private class User{ private String id; private User (String id){ this.id = id; } } }
  2. 實踐:將User修飾符改為public ,但將構造函數保持為私有,因此無法實例化。

    缺點:內部User類將作為AccountManager單例類的成員可見,這是不應該的。

    代碼示例

     public class AccountManager { private static final AccountManger ourInstance = new AccountManager(); private User user; public static AccountManager getInstance() { return ourInstance; } private AccountManger(){} public User getUser(){ return this.user; } public String getUserId() // <-- get User id { return user.id; } private class User{ private String id; private User (String id){ this.id = id; } } }
  3. 練習

  • 創建公共接口,例如IUser
  • 使內部類User實現該接口
  • 添加到外部類,在本例中是AccountManagerUser實例的 getter 方法

缺點:需要使用接口才能從User獲取數據。

代碼示例

    public class AccountManager {
    
    private static final AccountManager ourInstance = new AccountManager();
    private User user;

    public interface IUser{
        String getName();
    }

    private AccountManager(){}

    public static AccountManager getInstance(){
        return ourInstance;
    }

    public User getUser(){
        return this.user;
    }

    private class User implements IUser{
        private String id;

        private User(String id){
            this.id = id;
        }

        @Override
        public String getName() { // <-- get user id
            return id;
        }
    }
    }

所以你怎么看? 列出的選項中的任何一個? 其他方式?

謝謝您的意見

我會說User類需要是private的,並且AccountManager應該為它的屬性實現getterssetters

您不必知道什么是User ,因為AccountManager會告訴您您可以知道的內容。 另外,您可以遵守Demeter 法則,這總是一件好事。

IMO,內部類應該用作使外部類中的代碼更清晰的一種方式,並且它們不應該在其他地方使用。

但我想將User中的構造函數設為私有總比沒有好。

我看到三種替代方法:

  • 使 User 類獨立並公開(如有必要,給它一個 AccountManager 字段)。 然后 User 成為您的公共 API 的一部分 - 可能不是您想要的。

  • 在 AccountManager 類中,為公開相關的用戶屬性創建 getter 和 setter。 這使用戶實體成為帳戶管理器的不可見組件。 (打個比方:如果你談論你的汽車的馬力,你就在隱藏一個事實,即它不是汽車本身的屬性,而是它的引擎的屬性,這很好)。

  • 如果您希望用戶的概念成為您的 API 的一部分,但仍希望將您的內部 User 類保持私有,請使用公開相關的方法創建一個接口 IUser 並讓 User 實現 IUser。 然后你可以在你的 AccountManager 中公開一個public IUser getUser()方法,外界只能看到接口中聲明的功能。

看到AccountManager (你在你的代碼示例中拼錯了“Manager”)是一個單例類,它不會真正產生有效的區別,但你自己說“用戶類只對這個單例是唯一的”,所以目的如果將User類設為static ,可能會更好地表示它。

無論如何,在您的原始代碼示例中,您包含了一個方法public User getUser() 由於類Userprivate的,我真的看不出這樣做有什么意義,因為在類AccountManager之外,對User對象的任何引用都是無用的,因為您將永遠無法訪問其任何成員或聲明一個將由此獲得的User引用分配給的User變量。 我可以設想的唯一可能的用例是,如果AccountManager聲明了一個接受User參數的public (或任何高於User的訪問修飾符)方法。 但即使是這樣,我也會質疑這樣的設計是否真的是你想要的。

因此,您可能需要考慮是否真的需要public User getUser()方法,前提是User保持private 這已經讓我們想到了您最初的問題。 我認為您提出的第一個解決方案更好。 對我來說,這似乎正是允許超類訪問子類的“私有”成員的原因。 引用自 stackoverflow 上的這個答案

內部類(出於訪問控制的目的)被認為是包含類的一部分。 這意味着可以完全訪問所有私人。

因此,如果您認為UserAccountManager的一部分,那么您不必對從AccountManager內部訪問它的private字段而從User外部訪問它的私有字段感到內疚,因為顯然,Java 的設計者也會這樣想。

最后,如果您不打算在User存在期間更改字段id ,則可以將id設置為final

暫無
暫無

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

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