Предоставляет ли метод установки атрибуты? - PullRequest
0 голосов
/ 28 мая 2020

Допустим, в простом приложении для покупок есть класс Customer, класс продавца и класс Trade, и код выглядит просто так (чтобы проиллюстрировать мой вопрос):

 public class HelloWord {

    public static void main(String[] args) {

        Customer customer = new Customer();
        Seller seller = new Seller();

        Trade trade = new Trade(customer,seller);
        trade.buy(2);
    }

}

class Customer {
    private ArrayList<String> itemCart = new ArrayList<String>();
    private int gold = 100;

    public void setGold(int amount) {
        if (gold - amount >= 0) {
            gold -= amount;
        }
    }

    public int getGold() {
        return gold;
    }

    public void add(String item) {
        itemCart.add(item);
    }
}

class Seller {
    private ArrayList<String> itemCart = new ArrayList<String>();
    private ArrayList<Integer> itemsPrice = new ArrayList<Integer>();

    public int getItemPrice(int itemID) {
        return itemsPrice.get(itemID);
    }

    public String getItemById(int itemID) {
        return itemCart.get(itemID);
    }
}

class Trade {
    private Customer customer;
    private Seller seller;

    public Trade(Customer customer, Seller seller) {
        this.customer = customer;
        this.seller = seller;
    }

    public void buy(int itemID) {
        if (seller.getItemPrice(itemID) <= customer.getGold()) {
            customer.add(seller.getItemById(itemID));
            customer.setGold(seller.getItemPrice(itemID));
        } else {
            System.out.println("You don't have enough money to buy this item");
        }
    }
}

Мой вопрос: " Предоставляют ли методы "setGold" и "add" атрибуты? " Я не хочу, чтобы пользователь мог изменять itemCart и атрибут gold, просто вызывая метод add или setGold самостоятельно, но я хочу иметь возможность доступа к ним для изменения атрибутов с помощью других методов, в этом случае из метода «купить» в классе Trade.

Другими словами, мой вопрос: «Стоит ли мне беспокоиться, если к этому методу можно получить доступ из основного метода или это нормально и не нарушает целостность данных?»

Ответы [ 5 ]

1 голос
/ 28 мая 2020

Вы не получаете ожидаемого ответа, потому что вопрос немного сбивает с толку, как и сейчас. Внимательно читая его, вы не спрашиваете, может ли основной метод напрямую обращаться / изменять свойства Customer, но может ли метод main использовать методы add и setGold для изменения этих свойств. Кроме того, класс Seller просто добавляет энтропию, поскольку это не имеет отношения к вопросу.

Разбивка на части:

Предоставляют ли методы "setGold" и "add" атрибуты?

Сами атрибуты не отображаются, но оба методы позволяют изменять эти атрибуты извне, поскольку они объявлены как publi c.

я не хочу, чтобы пользователь мог изменять itemCart, ни атрибут gold buy, ни просто вызовите add метод или установить золото самостоятельно

Это возможно с вашим текущим кодом, так как add и setGold публикуются c. Это и есть цель public.

, но я хочу иметь к ним доступ, чтобы изменять их с помощью других методов, в данном случае из метода «купить» в классе Trade

Если вы хотите, чтобы add и setGold были видны только классу Trade, один из вариантов - поместить классы Trade и Customer в тот же пакет, что и в следующем примере:

com.example
    shopping
       |--- Customer.java
       |--- Trade.java
    application
       |--- HelloWorld.java

И затем сделайте оба метода package-private , например:

public Customer {
    // ... properties and other methods 

    void setGold(int amount) {
        if (gold - amount >= 0) {
            gold -= amount;
        }
    } 
    void add(String item) {
        itemCart.add(item);
    }
}

Отличие от вашего кода в том, что ни один из методов не содержит модификатора видимости (удален public ключевое слово), что делает их закрытыми для пакета и, следовательно, доступными только из одного и того же пакета.

С этой структурой и закрытыми для пакета методами в классе Customer, если вы вызываете add или setGold из класса main вы получите ошибку компилятора:

add(java.lang.String) is not public in com.example.shopping.Customer; 
cannot be accessed from outside package 

Но вы все равно можете получить к нему доступ из класса Trade, потому что он находится в том же пакете.

1 голос
/ 28 мая 2020

Я предлагаю вам изменить сеттер на обычную форму, и вы можете сделать его частным.

1 голос
/ 28 мая 2020

Цель инкапсуляции данных - скрыть реализацию объекта, гарантируя, что содержимое объекта можно изменить только через интерфейс объекта. Согласно этому определению, объект Trade по своей сути нарушает инкапсуляцию из-за своего конструктора. Поскольку вы передаете ссылки на клиента и продавца, любые инварианты, которые должен поддерживать объект Trade, могут быть нарушены человеком, непосредственно изменяющим покупателя или продавца. без дополнительного контекста, но возможное исправление может заключаться в передаче Покупателю и Продавцу при построении объекта Trade, передавая их в функцию покупки. Другое решение может заключаться в том, чтобы вместо этого прикрепить функцию покупки к объектам Customer или Seller, полностью избавившись от объекта Trade. Обычно классы в OOP представляют объекты, а не действия (за пределами определенных шаблонов проектирования).

1 голос
/ 28 мая 2020

Сеттер сам ничего не выставляет. Пока вы не открываете точные поля (например, вы не делаете getItemsPrice и , возвращая ArrayList), все в порядке.

Все ставки отключены с отражением, однако. Но дело не в этом.

1 голос
/ 28 мая 2020

Короткий ответ no, поскольку itemCart равен private, вызывающий во время выполнения не может получить к нему доступ напрямую.

Длинный ответ https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...