[英]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 方法來獲取用戶字段是最好的,但是由於內部類是私有的,所以這是不可能的。
可能的做法:
實踐:在外部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; } } }
實踐:將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; } } }
練習:
IUser
User
實現該接口AccountManager
到User
實例的 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
應該為它的屬性實現getters
和setters
。
您不必知道什么是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()
。 由於類User
是private
的,我真的看不出這樣做有什么意義,因為在類AccountManager
之外,對User
對象的任何引用都是無用的,因為您將永遠無法訪問其任何成員或聲明一個將由此獲得的User
引用分配給的User
變量。 我可以設想的唯一可能的用例是,如果AccountManager
聲明了一個接受User
參數的public
(或任何高於User
的訪問修飾符)方法。 但即使是這樣,我也會質疑這樣的設計是否真的是你想要的。
因此,您可能需要考慮是否真的需要public User getUser()
方法,前提是User
保持private
。 這已經讓我們想到了您最初的問題。 我認為您提出的第一個解決方案更好。 對我來說,這似乎正是允許超類訪問子類的“私有”成員的原因。 引用自 stackoverflow 上的這個答案:
內部類(出於訪問控制的目的)被認為是包含類的一部分。 這意味着可以完全訪問所有私人。
因此,如果您認為User
是AccountManager
的一部分,那么您不必對從AccountManager
內部訪問它的private
字段而從User
外部訪問它的私有字段感到內疚,因為顯然,Java 的設計者也會這樣想。
最后,如果您不打算在User
存在期間更改字段id
,則可以將id
設置為final
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.