访问私有数组中对象的私有变量

Access to private variables of Objects that are within a private array

我想创建一个可以有多个菜单的 Restaurant 对象。每个菜单可以有多个类别,每个类别可以有多个项目。每件商品都有名称、价格和描述。

--Company--
  -Menu ONE-
  -Menu Name-
    -Category ONE-
       -Category Name-
       -Menu Item ONE-
         -Menu Item Name
         -Menu Item Price
         -Menu Item Description
       -Menu Item TWO-
    -Category TWO-
  -Menu TWO- 

示例 class没有构造函数、getters / setter 或方法。

拥有一系列菜单的公司

    public class Company
    {   
        // Class constants

        // Class variables
        private String companyName;   //  Stores company name
        private String hours;         //  Restaurant hours
        private String phoneNumber;   //  Restaurant phone number
        private Menu[] menuList;      //  Array of menu objects
        private int menuCount;        //  Number of menus in the array

     }

包含类别数组的菜单

    public class Menu
    {   
        // Class constants

        // Class variables
        private String menuName;           //  Name of Menu
        private Category[] categoryList;   //  Array of category objects
        private int categoryCount;         //  Number of categories in the array

     }

包含菜单项数组的类别

    public class Category
    {   
        // Class constants

        // Class variables
        private String categoryName;       //  Name of Menu
        private MenuItem[] menItemList;    //  Array of MenuItem objects
        private int menuItemCount;         //  Number of menu items in the array

     }

具有名称、价格和描述的单行项目

    public class MenuItem
    {   
        // Class constants

        // Class variables
        private String name;        //  Name of Menu Item
        private float price;        //  Price of the Menu Item
        private String description; //  Description of the Menu Item

     }

在驱动程序 class 中,如果我只能访问公司的方法,我将如何更改菜单项中的任何内容?

我考虑过为每个私有项目数组设置一个 getter,但是向下挖掘 3 个级别进入私有数组似乎很难实现。它不像 Company.Menu.Category.MenuItem.editName(newName);

那么简单

注意* 我对 "Should use a Linked list or ArrayList" 答案不感兴趣。程序要求需要基本数组。

让我知道是否需要更清楚,或者您是否想要 SSCCE。

如果您为必须从外部读取的成员创建 getter 方法,则必须深入挖掘才能从 Menu 对象中获取所需的信息。这就是封装的意义所在。如果将重复这些操作,您可以创建一个助手 class / 方法来管理数组的各个级别。

. 的链接是避免它的不好的做法,您可以执行以下操作

在class公司

中创建方法modifyMenu
  public class Company {
       public modifyMenu (int menuIndexToModify, int categoryIndex, MenuItem itemWithModification){
            menuList[menuIndexToModify].modifyMenuItem(categoryIndex, menuItemIndex, itemWithModification);
      }
  }

Menu class

中创建方法 modifyMenuItem
 public class Menu{
    public void modifyMenuItem(int categoryIndex, int menuItemIndex, MenuItem itemWithModification){
              categoryList[categoryIndex].modifyMenuItem(menuItemIndex,itemWithModification);
    }
 }

在 Class 中创建 modifyMenuItem 方法 Category

public class Category{
    public void modifyMenuItem(int menuItemIndex, MenuItem itemWithModification){
            menuItemList[menuItemIndex].modify(itemWithModification);
     }
 }

克里特方法 modify MenuItem

 public void modify( MenuItem itemWithModification){
      this.name = itemWithModification.name
      // assign other stes similarly
 }

现在你只需要调用方法 modifyMenu ,将参数传递给它。

I thought about having a getter for each private array of items, but digging down 3 levels into private arrays seems very difficult to implement. It's not as simple as Company.Menu.Category.MenuItem.editName(newName);

实现起来并不难,但是调用连续的 getter 是一种反模式,例如:

company.getMenu().getCategory().getMenuItem().editName(newName);

Demeter law 状态为:

Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.

Each unit should only talk to its friends; don't talk to strangers.

Only talk to your immediate friends.

因此,要解决您的问题,您将不得不重构您的设计,使您的对象相互协作。

Collaborating/Cascading接近

您可以定义一个 editItemName() 方法,该方法由层次结构中的每个对象依次调用。

Company可以定义方法如:

public void editItemName(String menuName, String categoryName, String itemName, String newName){ 
   Menu menu = findMenu(menuName);
   menu.editItemName(category, item, newName);
}

Menu可以定义方法如:

public void editItemName(String categoryName, String itemName, String newName){ 
   Category category = findCategory(categoryName);
   category.editItemName(item, newName);
}

Category可以定义方法如:

public void editItemName(String itemName, String newName){ 
   MenuItem item = findItem(itemName);
   item.editItemName(newName);
}

最后MenuItem可以定义如下方法:

public void editItemName(String newName){
   this.name = newName;
}

更直接的方法(如果适用)

传递这么多参数对客户来说可能很麻烦。 作为替代方案,如果 Item 对象是唯一的(就 equals() 而言)并且您可以从客户端获取它,您可以使事情变得更简单。 您可能只需要将 MenuItem(叶子)中的方法定义为:

public void editItemName(String newName){
   this.name = newName;
}

您可以定义一个按标识符存储项目的地图:

Map<String, MenuItem> mapUniqueItems = new HashMap<>();
// add items in the map
mapUniqueItems.put("item1", new MenuItem(..));
mapUniqueItems.put("item2", new MenuItem(..));
// add items in the hierarchy as you actually do
...

稍后您可以根据其 ID 编辑项目,例如:

String itemIdentifier = ...;
MenuItem item = mapUniqueItems.get(itemIdentifier);
item.editItemName("new value");