对 Java 中的 typedef 等价物使用包装器 class;我必须公开 class 变量吗?
Using a wrapper class for a typedef equivalent in Java; must I expose the class variable?
我想我在这里遗漏了一些基本的东西。在编写纸牌游戏应用程序时,我定义了一张卡片 class,然后是以下形式的各种卡片集合:
ArrayList<Card> cards;
现在我当然可以继续使用所有适当的 ArrayList 方法。
有时我厌倦了写 ArrayList,并且还需要创建 ArrayList 的数组,所以定义一个包装器 class 像这样:
class CardList {
protected ArrayList<Card> cards;
...overrides and class methods down here...
}
但是现在当我实例化一个 CardList(比如 MyCardList)时,我无法访问底层 ArrayList 方法,所以我似乎可以选择:
(a) 将卡片公开为受包保护的成员,这样我就可以编写 MyCardList.cards.someArrayListMethod() OR
(b) 或在 CardList 中为我想使用的每个 ArrayList 方法实现直通方法
哪个更好,还是我已经无可救药地偏离了轨道?
您可以像这样创建包范围的 class:
class CardList extends ArrayList<Card> {
// Literally no need for anything here unless you want
// constructors that accept capacity, etc.; the default
// constructor will be provided
}
...然后使用它:
CardList list = new CardList();
list.add(new Card());
// ...
但编写接口代码通常更好,在这种情况下:
interface CardList extends List<Card> {
// No need for anything here
}
和
class CardListImpl extends ArrayList<Card> implements CardList {
// No need for anything here unless you want constructors
// that accept capacity, etc.
}
并使用它:
CardList list = new CardListImpl();
list.add(new Card());
// ...
...然后您可以切换到 LinkedList<Card>
,如果您愿意,只需更改一个文件即可。
或者就此而言,您实际上并不需要 CardList
界面 — CardList
仅比 List<Card>
短两个字符。那就是:
class CardListImpl extends ArrayList<Card> {
// No need for anything here unless you want constructors
// that accept capacity, etc.
}
并使用它:
List<Card> list = new CardListImpl();
list.add(new Card());
// ...
...同样,如果您决定切换具体列表的类型 class,您只需在一个地方进行。
直接暴露卡片总是一个坏主意。如果您需要访问它,请使用 getter(public,根据需要进行保护或包保护)如果您公开该字段,则可能会导致用户将其设置为 null
如果需要,您可以委托 arraylist 方法,如果您在 CardList 中组合多个元素,这会更有意义
另一种可能性是扩展 ArrayList,但这只有在您需要特定功能时才有意义(例如,在添加已在列表中的卡片时您可能需要特定行为)
第四种可能性是只委托您需要的方法,这样您就可以自由地更改实现(例如,如果每张卡片都是唯一的,您可以使用 int 或 long 来跟踪每张卡片的存在,而不是它出现在列表中)
我想我在这里遗漏了一些基本的东西。在编写纸牌游戏应用程序时,我定义了一张卡片 class,然后是以下形式的各种卡片集合:
ArrayList<Card> cards;
现在我当然可以继续使用所有适当的 ArrayList 方法。
有时我厌倦了写 ArrayList,并且还需要创建 ArrayList 的数组,所以定义一个包装器 class 像这样:
class CardList {
protected ArrayList<Card> cards;
...overrides and class methods down here...
}
但是现在当我实例化一个 CardList(比如 MyCardList)时,我无法访问底层 ArrayList 方法,所以我似乎可以选择:
(a) 将卡片公开为受包保护的成员,这样我就可以编写 MyCardList.cards.someArrayListMethod() OR
(b) 或在 CardList 中为我想使用的每个 ArrayList 方法实现直通方法
哪个更好,还是我已经无可救药地偏离了轨道?
您可以像这样创建包范围的 class:
class CardList extends ArrayList<Card> {
// Literally no need for anything here unless you want
// constructors that accept capacity, etc.; the default
// constructor will be provided
}
...然后使用它:
CardList list = new CardList();
list.add(new Card());
// ...
但编写接口代码通常更好,在这种情况下:
interface CardList extends List<Card> {
// No need for anything here
}
和
class CardListImpl extends ArrayList<Card> implements CardList {
// No need for anything here unless you want constructors
// that accept capacity, etc.
}
并使用它:
CardList list = new CardListImpl();
list.add(new Card());
// ...
...然后您可以切换到 LinkedList<Card>
,如果您愿意,只需更改一个文件即可。
或者就此而言,您实际上并不需要 CardList
界面 — CardList
仅比 List<Card>
短两个字符。那就是:
class CardListImpl extends ArrayList<Card> {
// No need for anything here unless you want constructors
// that accept capacity, etc.
}
并使用它:
List<Card> list = new CardListImpl();
list.add(new Card());
// ...
...同样,如果您决定切换具体列表的类型 class,您只需在一个地方进行。
直接暴露卡片总是一个坏主意。如果您需要访问它,请使用 getter(public,根据需要进行保护或包保护)如果您公开该字段,则可能会导致用户将其设置为 null
如果需要,您可以委托 arraylist 方法,如果您在 CardList 中组合多个元素,这会更有意义
另一种可能性是扩展 ArrayList,但这只有在您需要特定功能时才有意义(例如,在添加已在列表中的卡片时您可能需要特定行为)
第四种可能性是只委托您需要的方法,这样您就可以自由地更改实现(例如,如果每张卡片都是唯一的,您可以使用 int 或 long 来跟踪每张卡片的存在,而不是它出现在列表中)