Инкапсуляция - зачем она нужна, когда сеттеры уже общедоступны? [Дубликат]

Класс, где мы переопределяем метод finalize

public class TestClass {    
    public TestClass() {
        System.out.println("constructor");
    }

    public void display() {
        System.out.println("display");
    }
    @Override
    public void finalize() {
        System.out.println("destructor");
    }
}

Шансы на метод finalize, который вызывается

public class TestGarbageCollection {
    public static void main(String[] args) {
        while (true) {
            TestClass s = new TestClass();
            s.display();
            System.gc();
        }
    }
}

, когда память перегружена объектами дампа, gc вызовет метод завершения

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

29
задан Danyal Sandeelo 3 August 2018 в 06:15
поделиться

5 ответов

Я полностью согласен с ответом Конамимана , но я хотел бы добавить одну вещь:

Есть случаи, когда вы действительно не хотите эту абстракцию , И это нормально.

Простой пример, который я хотел бы использовать здесь, - это класс для трехмерного вектора с плавающей точкой:

class Vector3f {
public:
    float x;
    float y;
    float z;
};

Не могли бы вы сделать эти поля приватными и предоставить вместо них сеттеры? Конечно, вы могли бы. Но здесь вы можете возразить, что класс действительно должен обеспечивать набор чисел с плавающей точкой, и вам не нужны никакие дополнительные функции. Таким образом, добавление сеттеров только усложнит класс, и вы предпочитаете оставлять поля открытыми.

Теперь вы можете легко создавать сценарии, в которых это может укусить вас позже. Например, однажды вы можете получить требование, чтобы Vector3f не разрешалось хранить NaN, и должно выдавать исключение, если кто-то пытается это сделать. Но такой гипотетической проблемы будущего не должно быть достаточно, чтобы оправдать введение дополнительных абстракций.

Это ваш вызов как программиста, чтобы решить, какие абстракции имеют смысл для рассматриваемой проблемы, а какие только помешают вам выполнить работу. Ненужные абстракции являются чрезмерно инженерными и повредят вашу производительность так же, как и недостаточное абстрагирование.

Итог: не вслепую везде используйте сеттеры только потому, что кто-то утверждал, что это хорошая практика. Вместо этого подумайте о проблеме и подумайте о компромиссах.

23
ответ дан Community 3 August 2018 в 06:15
поделиться
  • 1
    @LukaRahne Не, если по крайней мере одна из отдельных сумм превышает 32 (согласно Вашему примеру) разрядный предел. В этом случае, поскольку xanatos показал выше, каждый попадает в беду. – legrojan 14 August 2015 в 12:12
  • 2
    @LukaRahne Не, если по крайней мере одна из отдельных сумм превышает 32 (согласно Вашему примеру) разрядный предел. В этом случае, поскольку xanatos показал выше, каждый попадает в беду. – legrojan 14 August 2015 в 12:12
  • 3
    @LukaRahne Не, если по крайней мере одна из отдельных сумм превышает 32 (согласно Вашему примеру) разрядный предел. В этом случае, поскольку xanatos показал выше, каждый попадает в беду. – legrojan 14 August 2015 в 12:12
  • 4
    @LukaRahne Не, если по крайней мере одна из отдельных сумм превышает 32 (согласно Вашему примеру) разрядный предел. В этом случае, поскольку xanatos показал выше, каждый попадает в беду. – legrojan 14 August 2015 в 12:12
  • 5
    @LukaRahne Не, если по крайней мере одна из отдельных сумм превышает 32 (согласно Вашему примеру) разрядный предел. В этом случае, поскольку xanatos показал выше, каждый попадает в беду. – legrojan 14 August 2015 в 12:12

Хотя ответ Конамимана является точным, я хотел бы добавить, что в конкретном случае открытых сеттеров по сравнению с прямым представлением открытых полей, о которых вы спрашиваете, существует еще одно очень важное различие, которое следует иметь в виду, помимо сокрытия информации и , отделяющего реализацию от общедоступной поверхности или API класса; Проверка .

В сценарии открытого поля нет способа проверить значение поля при его изменении. В случае с общедоступным установщиком (будь то свойство Foo {get; set;} или SetFoo(Foo value)) у вас есть возможность добавить проверочный код и запустить необходимые побочные эффекты, и таким образом убедиться, что ваш класс всегда находится в допустимом или предсказуемом состоянии .

5
ответ дан Community 3 August 2018 в 06:15
поделиться

Что если вы хотите проверить диапазон перед назначением? Это один из случаев, когда я использую сеттеры и геттеры

3
ответ дан Ali Burak Kulakli 3 August 2018 в 06:15
поделиться
  • 1
    Так, Узел 0.6.18 отсутствует теперь, это - просто случай записи сценария установки или там больше, чтобы сделать? – Tony Blundell 22 May 2012 в 17:56
  • 2
    Так, Узел 0.6.18 отсутствует теперь, это - просто случай записи сценария установки или там больше, чтобы сделать? – Tony Blundell 22 May 2012 в 17:56
  • 3
    Так, Узел 0.6.18 отсутствует теперь, это - просто случай записи сценария установки или там больше, чтобы сделать? – Tony Blundell 22 May 2012 в 17:56
  • 4
    Так, Узел 0.6.18 отсутствует теперь, это - просто случай записи сценария установки или там больше, чтобы сделать? – Tony Blundell 22 May 2012 в 17:56
  • 5
    Так, Узел 0.6.18 отсутствует теперь, это - просто случай записи сценария установки или там больше, чтобы сделать? – Tony Blundell 22 May 2012 в 17:56

В Википедии есть хороший обзор [методов мутатора ( https://en.wikipedia.org/wiki/Mutator_method ), которые представляют собой методы установки и как они работают на разных языках.

Краткая версия: если вы хотите ввести валидацию или другую логику, которая выполняется при модификации объекта, было бы неплохо иметь установщик, чтобы вставить эту логику. Также вы можете скрыть, как вы храните вещи. Таким образом, это причины наличия геттеров / сеттеров. Точно так же для получателей вы можете иметь логику, которая предоставляет значения по умолчанию или значения, которые зависят, например, от конфигурация для таких вещей, как Locale, кодировка символов и т. д. Есть много веских причин, чтобы хотеть иметь логику, кроме получения или установки переменной экземпляра.

Очевидно, что если у вас есть геттеры и сеттеры, вы не хотите, чтобы люди обходили их, напрямую манипулируя состоянием объекта, поэтому вы должны сохранять переменные экземпляра закрытыми.

Другие вопросы, которые следует учитывать, включают в себя, хотите ли вы, чтобы ваши объекты вообще были изменяемыми (если нет, делайте поля окончательными), хотите ли вы сделать изменение состояния объекта потокобезопасным, например, с помощью. замки, синхронизированные и т. д.

2
ответ дан Jilles van Gurp 3 August 2018 в 06:15
поделиться

Установка полей в качестве личных документов является мощным фактом: эти частные поля используются только непосредственно в текущем классе. Это помогает сопровождающим, не отслеживая использование поля. Они могут лучше рассуждать о коде, взглянув на класс и определив, что воздействие на эти поля и из них в среде класса проходит через публичные и защищенные вызовы методов. Это ограничивает поверхность воздействия на класс.

В свою очередь, определение «установщика» для частного поля не означает, что оно снова станет публичным. Речь идет об объявлении еще одного мощного факта: объект , принадлежащий этому классу, обладает свойством , которое может быть изменено извне. (Термины object и property используются в смысле ограниченной части целого и наблюдаемого факта об этой части , не в смысле ООП)

Почему тогда было бы достаточно объявить «установщик» для поля, если оно будет общедоступным? Поскольку объявляет , поле не только привязывает имя к свойству объектов класса, но также обязуется использовать память для этого свойства.

Поэтому, если вы объявляете «личное поле с установщиком», вы объявляете три вещи:

  • Вы объявляете, что имя, которое вы дали кластеру поля / сеттера, представляет свойство объекта, который представляет интерес, когда объект рассматривается как черный ящик.
  • Вы заявляете, что значение этого свойства может изменяться средой объекта.
  • Вы заявляете, что в этом конкретном конкретном классе свойство объекта реализуется путем выделения ему некоторого объема памяти.

Я выступаю за то, чтобы вы никогда не делали свои поля закрытыми с геттерами и сеттерами без разбора. Поля для описания хранения. Методы для взаимодействия с окружающей средой. (А частный случай «геттеров» и «сеттеров» предназначен для описания свойств , представляющих интерес)

2
ответ дан Laurent LA RIZZA 3 August 2018 в 06:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: