Будуйте як об'єкти на Java


195

Чи повністю проти Java способу створення об'єктів, подібних структурам?

class SomeData1 {
    public int x;
    public int y;
}

Я бачу клас з аксесуарами та мутаторами, які більше схожі на Java.

class SomeData2 {
    int getX();
    void setX(int x);

    int getY();
    void setY(int y);

    private int x;
    private int y;
}

Клас з першого прикладу нотаційно зручний.

// a function in a class
public int f(SomeData1 d) {
    return (3 * d.x) / d.y;
}

Це не так зручно.

// a function in a class
public int f(SomeData2 d) {
    return (3 * d.getX()) / d.getY();
}

9
Замість загальнодоступних полів, що змінюються, розгляньте або загальнодоступні поля, що змінюються, або поля, що змінюються в локальному пакеті. Або краще було б IMHO.
Пітер Лоурі

Пам’ятайте, що, хоча геттери і сетери некрасиві / багатослівні, це своєрідне серце Яви. Це ненакорочена мова. З іншого боку, однак, НІКОЛИ не слід вводити нічого з цього, оскільки саме це робить для вас IDE. На динамічній мові вам потрібно вводити менше, але ви повинні вводити (як правило, хоча IDE можуть допомогти).
Дан Розенстарк

Як не дивно, хоча OO має свої сильні сторони в плані інкапсуляції, це є платна CPU і зберігання. Колекціонер сміття (майже повністю) усуває необхідність турбуватися про те, коли слід очистити посилання на об'єкти. Нинішня тенденція проходить повним колом, використовуючи С-подібні конструкції в небі. Це ідеально підходить для кеш-рішень, міжпроцесорних комунікацій, більш швидких операцій з оперативною пам’яттю, зниженням GC o / h і навіть може отримати вигоду з меншої o / h для ваших наборів даних. Якщо ви знаєте, що робите, ви б не ставили цього питання ... тому подумайте ще раз!
user924272

@ user924272: Re "Поточна тенденція йде повним колом, використовуючи структури, схожі на С", без похилого ". Що б ви зробили на Java як ??? ІМХО, це область, де Java демонструє свій вік ...
ToolmakerSteve

@ToolmakerSteve - я бачу коло. Я не єдиний. Такі компанії, як Azul, готуються до збору сміття без пауз. Ява стара. Правда. Інженери, які помічають слабкість і щось з цим роблять, а не стогнуть? Вони заслуговують на повагу! +10 до Азула від мене :-)
user924272

Відповіді:


62

Це поширена тема. Недолік створення публічних полів в об'єктах полягає в тому, що ви не маєте контролю над значеннями, які йому задаються. У групових проектах, де багато програмістів, які використовують один і той же код, важливо уникати побічних ефектів. Крім того, іноді краще повернути копію об’єкта поля або якось перетворити його тощо. Ви можете знущатися над такими методами у своїх тестах. Якщо ви створюєте новий клас, можливо, ви не побачите всіх можливих дій. Це як оборонне програмування - коли-небудь геттери та сетери можуть бути корисними, і створити / використовувати їх не коштує багато. Тому вони іноді корисні.

На практиці більшість полів мають прості геттери та сетери. Можливе рішення виглядатиме так:

public property String foo;   
a->Foo = b->Foo;

Оновлення: Навряд чи підтримка властивостей буде додана в Java 7 або, можливо, коли-небудь. Інші мови JVM, такі як Groovy, Scala тощо, зараз підтримують цю функцію. - Алекс Міллер


28
Це дуже погано, мені подобаються властивості C # -style (це звучить як те, про що ви говорите)
Джон Онстотт

2
Тому використовуйте перевантаження ... private int _x; public void x (значення int) {_x = значення; } public int x () {return _x; }
Гордон

12
Я вважаю за краще використовувати =, що, на мій погляд, робить код більш чистим.
Свиш

6
@ T-Bull: Тільки тому, що ви МОЖЕТЕ мати два xs - це дві різні речі, це не робить його гарною ідеєю. ІМХО, це погана пропозиція, оскільки це може призвести до плутанини людських читачів. Основний принцип: не змушуйте читача робити двічі; дайте зрозуміти, що ви говорите - Використовуйте різні назви для різних сутностей. Навіть якщо різниця полягає лише в тому, щоб передбачити підкреслення. Не розраховуйте навколишні пунктуації для розмежування сутностей.
ToolmakerSteve

2
@ToolmakerSteve: Це "може призвести до плутанини" - це найпоширеніший і все ще найслабший аргумент, коли мова йде про захист догми кодування (на відміну від стилю кодування). Завжди є хтось, кого МОЖЕ бентежити найпростіші речі. Ви завжди знайдете когось, хто скаржиться на те, що він допустив помилку після того, як залишався неспаним і кодував протягом півроку або щось подібне, а потім звинувачує в оманливому стилі кодування. Я не даю цього рахувати. Цей стиль є дійсним, очевидним і забезпечує чистоту простору імен. Крім того, тут немає різних об'єктів, навколо них є / one / entity та деякий код котла.
T-Bull

290

Виявляється, що багато людей з Java не знайомі з Посібниками з кодування Sun Java, які говорять, що цілком доречно використовувати загальну змінну екземпляра, коли клас по суті є "Struct", якщо Java підтримує "struct" (коли немає поведінки).

Люди схильні думати, що геттери та сетери є способом Java, ніби вони лежать в основі Java. Це не так. Якщо ви дотримуєтесь Правил кодування Sun Java, використовуючи загальнодоступні змінні екземплярів у відповідних ситуаціях, ви насправді пишете кращий код, ніж захаращувати його непотрібними геттерами та сеттерами.

Конвенції Java-коду від 1999 року і досі залишаються незмінними.

10.1 Надання доступу до змінних інстанцій та класів

Не оприлюднюйте жодних змінних примірників чи класів без поважних причин. Часто змінні екземпляри не потрібно чітко встановлювати або отримувати - часто це відбувається як побічний ефект викликів методів.

Одним із прикладів відповідних змінних публічних примірників є випадок, коли клас по суті є структурою даних без поведінки. Іншими словами, якщо ви використовували б структуру замість класу (якщо підтримка Java підтримувала структуру), то доречно зробити загальнодоступними змінні екземпляра класу .

http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-137265.html#177

http://en.wikipedia.org/wiki/Plain_old_data_structure

http://docs.oracle.com/javase/1.3/docs/guide/collections/designfaq.html#28


88
+1 За те, що насправді має авторитетне джерело. Кожна інша відповідь - люди, які обертаються своєю думкою, ніби вони факти.
ArtOfWarfare

1
Існує специфікація Java Beans, яка є стандартним способом доступу до властивостей за допомогою методів get і set ... див . Огляд на en.wikipedia.org/wiki/JavaBeans .
user924272

4
@ user924272: Яким чином у цій відповіді є відповідна специфікація Java Beans, яка обговорює, коли доцільно використовувати "змінні загальнодоступних екземплярів"? Якби специфікація була стандартним способом автоматичного перетворення змінних екземплярів у властивості, ala C #, це може бути доречним. Але це не так, правда? Він просто вказує найменування котлів та установок, які потрібно створити, щоб зробити таке відображення.
ToolmakerSteve

@ToolmakerSteve. Це питання Java. Крім того, питання ухиляється від поширеної проблеми там, де існує специфікація. З точки зору старої школи, набагато простіше налагоджувати мутації поля, коли існує стандартний спосіб зробити це - встановити точку розриву на сетері. Це, мабуть, застаріло за допомогою сучасних налагоджувачів, але я змушений нахмуритися на класи, які безпосередньо "пробивають" об'єкти ... хоча для менших додатків це нормально, це справжній головний біль для великих додатків і великих організацій
user924272

223

Справді використовуйте здоровий глузд. Якщо у вас є щось на кшталт:

public class ScreenCoord2D{
    public int x;
    public int y;
}

Тоді немає сенсу загортати їх у геттери та сетери. Ви ніколи не збираєтесь зберігати x, y координату в цілих пікселях будь-яким іншим способом. Геттери і сетери лише уповільнить вас.

З іншого боку, з:

public class BankAccount{
    public int balance;
}

Ви можете змінити спосіб обчислення балансу в якийсь момент майбутнього. Для цього справді слід використовувати геттери та сетери.

Завжди бажано знати, чому ви застосовуєте належну практику, щоб ви знали, коли нормально виконувати правила.


3
Я продовжую цю відповідь і кажу ще, що ви можете створити клас із загальнодоступними полями до тих пір, поки поля будуть жирними незалежними один від одного. тобто одне поле не залежить від іншого. Це може бути досить корисним у багатьох випадках для кількох повернених значень функції або для полярних коодинатів. {кут, довжина}, які йдуть разом, але не залежать один від одного жодним внутрішнім способом.
Spacen Jasset

@SpacenJasset: FYI, я не бачу, як ваші приклади (кілька повернених значень; полярні координати) мають відношення до того, чи слід використовувати публічні поля проти геттера / сеттера. У випадку декількох повернених значень це може бути навіть контрпродуктивним, оскільки, ймовірно, абонент повинен отримувати лише повернені значення, що аргументує користь публічних одержувачів та приватних установників (незмінних). Це може бути справедливим і для повернення полярних координат з (x, y) об'єкта - врахуйте АККУМУЛЯТИВНІ математичні помилки, оскільки зміни окремих компонентів полярної координати перетворюються назад у (x, y).
ToolmakerSteve

@SpacenJasset: Але я згоден з вашим принципом.
ToolmakerSteve

1
У вас є дійсна точка, але я вважаю, що річ із пікселями - це поганий приклад, оскільки переконання, що піксель знаходиться у вікні (лише приклад) - це те, що хтось може зробити, і до того ж, дозволити комусь встановити піксель, (-5, -5)можливо, це не буде гарна ідея. :-)
Horsey

50

Для вирішення проблем, пов’язаних із змінністю, ви можете оголосити x та y як остаточні. Наприклад:

class Data {
  public final int x;
  public final int y;
  public Data( int x, int y){
    this.x = x;
    this.y = y;
  }
}

Код виклику, який намагається записати в ці поля, отримає помилку часу компіляції "поле x оголошено остаточним; не може бути призначене".

Потім клієнтський код може мати зручність "короткої руки", яку ви описали у своїй публікації

public class DataTest {
    public DataTest() {
        Data data1 = new Data(1, 5);
        Data data2 = new Data(2, 4);
        System.out.println(f(data1));
        System.out.println(f(data2));
    }

    public int f(Data d) {
        return (3 * d.x) / d.y;
    }

    public static void main(String[] args) {
        DataTest dataTest = new DataTest();
    }
}

3
Спасибі - відповідь, корисна та стисла. Показує, як отримати перевагу синтаксису поля, коли не хочеться змінити.
ToolmakerSteve

@ToolmakerSteve - дякую за відгуки - дуже вдячний.
Брайан

Я намагався використати кінцеві екземпляри остаточного класу з заключними полями як структура "екземпляри", але в caseвиразі, що посилається на таке поле екземпляра, я отримав Case expressions must be constant expressions. який шлях до цього? яка тут ідіоматична концепція?
n611x007

1
остаточні поля все ще є посиланнями на об'єкти, які не є константами, оскільки вони будуть ініціалізовані при першому використанні класу. Компілятор не може знати "значення" посилань на об'єкт. Константи повинні бути відомі при складанні.
Йохан Тіден

1
+1 Дійсно важлива відповідь. На мою думку, корисність непорушних класів не можна недооцінювати. Їх семантика "пожежа і забудь" робить міркування про код часто простішими, особливо в багатопотокових середовищах, де їх можна ділити довільно між потоками без синхронізації.
Оператор

11

Не використовувати public поля

Не використовуйте publicполя, коли ви дійсно хочете обговорити внутрішню поведінку класу. Візьмемо java.io.BufferedReaderдля прикладу. Він має таке поле:

private boolean skipLF = false; // If the next character is a line feed, skip it

skipLFчитається і пишеться всіма способами читання. Що робити, якщо зовнішній клас, що працює в окремому потоці, зловмисно змінив стан skipLFпосеред прочитаного? BufferedReaderобов'язково піде сіно.

Використовуйте publicполя

Візьмемо Pointдля прикладу цей клас:

class Point {
    private double x;
    private double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public double getX() {
        return this.x;
    }

    public double getY() {
        return this.y;
    }

    public void setX(double x) {
        this.x = x;
    }

    public void setY(double y) {
        this.y = y;
    }
}

Це зробить обчислення відстані між двома точками дуже болісно писати.

Point a = new Point(5.0, 4.0);
Point b = new Point(4.0, 9.0);
double distance = Math.sqrt(Math.pow(b.getX() - a.getX(), 2) + Math.pow(b.getY() - a.getY(), 2));

Клас не має жодної поведінки, крім звичайних геттерів та сеттерів. Прийнятно використовувати загальнодоступні поля, коли клас представляє лише структуру даних, а не має і ніколи не матиме поведінки (тонкі геттери та сетери не є вважаються поведінкою). Це можна записати краще таким чином:

class Point {
    public double x;
    public double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
}

Point a = new Point(5.0, 4.0);
Point b = new Point(4.0, 9.0);
double distance = Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));

Чисто!

Але пам’ятайте: не тільки ваш клас повинен бути відсутнім у поведінці, але він також не повинен мати причин мати поведінку і в майбутньому.


(Саме так описується ця відповідь . Цитувати "Конвенції про коди для мови програмування Java: 10. Практики програмування" :

Одним із прикладів відповідних змінних публічних примірників є випадок, коли клас по суті є структурою даних без поведінки. Іншими словами, якщо ви використовували б structзамість класу (якщо підтримується Java struct), то доречно зробити загальні змінні екземплярів класу.

Тож офіційна документація також приймає цю практику.)


Крім того, якщо ви впевнені, що члени вищого Pointкласу повинні бути незмінні, ви можете додати finalключове слово для його виконання:

public final double x;
public final double y;

8

До речі, структура, яку ви наводите як приклад, вже існує в бібліотеці базового класу Java як java.awt.Point. Він має x та y як публічні поля, перевірте це на собі .

Якщо ви знаєте, чим займаєтесь, і інші у вашій команді знають про це, тоді добре мати публічні поля. Але вам не слід покладатися на це, оскільки вони можуть викликати головні болі, як у помилок, пов’язаних з розробниками, які використовують об'єкти, як якщо б вони були виділені структурами стеків (об'єкти java завжди надсилаються до методів як посилання, а не як копії).


+1 Добре згадування про проблему - спосіб, коли результат все ще НЕ схожий на С-структуру. Однак питання, яке ви ставите перед об'єктами java, що завжди є посиланням, не вдосконалюється, створюючи сеттер замість того, щоб мати публічне поле для запису (що суть питання ОП - яке представлення використовувати). Швидше, це аргумент на користь робити НІКОЛИ. Це аргумент для непорушності. Що може бути зроблено як на public finalмісцях, як у відповіді Брайана, або за допомогою публічного геттера, але без публічного сетера. Тобто, чи використовує поле чи аксесуари, не має значення.
ToolmakerSteve

8

Re: aku, izb, John Topley ...

Слідкуйте за проблемами, що стосуються змін ...

Можливо, здається розумним опускати геттерів / сетерів. Насправді це може бути нормально в деяких випадках. Справжня проблема запропонованого тут малюнка - це незмінність.

Проблема полягає в тому, що коли ви передаєте посилання на об'єкт, що містить не остаточні, загальнодоступні поля. Все, що має посилання, може змінювати ці поля. Ви більше не маєте контролю над станом цього об’єкта. (Подумайте, що було б, якщо Strings були мутаційними.)

Стає погано, коли цей об'єкт є важливою частиною внутрішнього стану іншого, ви тільки що піддалися внутрішній реалізації. Для запобігання цього потрібно замість цього повернути копію об'єкта. Це працює, але може спричинити величезний тиск GC від тонн створених одноразових копій.

Якщо у вас є загальнодоступні поля, розгляньте можливість створення класу лише для читання. Додайте поля як параметри до конструктора та позначте поля остаточними. В іншому випадку переконайтеся, що ви не відкриваєте внутрішній стан, і якщо вам потрібно створити нові екземпляри для зворотного значення, переконайтеся, що воно не буде викликано надмірно.

Дивіться: " Ефективна Java " Джошуа Блоха - Пункт №13: Незмінна користь.

PS: Також пам’ятайте, що всі JVM в ці дні оптимізують метод getMethod, якщо це можливо, в результаті чого вийде лише одна інструкція з читання на місцях.


12
Як вирішувач вирішує цю проблему. Ви все ще маєте посилання, у вас немає синхронізації з операціями. Геттери / сетери не забезпечують захисту самі по собі.
he_the_great

1
Геттери та сетери можуть забезпечити синхронізацію за потреби. Ви також очікуєте, що геттери та сетери зроблять набагато більше, ніж було зазначено. Незалежно від цього проблема синхронізації все ще нагадує.
користувач924272

7

Я спробував це в декількох проектах, з теорії про те, що геттери та сетери захаращують код семантично безглуздою суттю, і що інші мови, здається, чудово справляються з приховуванням даних, заснованим на конвенції, або розподілом обов'язків (наприклад, python).

Як зазначали інші, у вас виникають дві проблеми, і вони насправді не виправні:

  • Практично будь-який автоматизований інструмент у світі Java покладається на конвенцію про геттер / сетер. Діто для, як зазначають інші, теги jsp, конфігурація весни, інструменти затемнення тощо, тощо. Боротьба з тим, що очікують побачити ваші інструменти, - це рецепт тривалих сеансів, за допомогою яких можна шукати нестандартний спосіб ініціювання. ясна квасоля. Дійсно не вартий клопоту.
  • Після того, як у вас буде елегантно кодований додаток із сотнями загальнодоступних змінних, ви, ймовірно, знайдете хоча б одну ситуацію, коли їх недостатньо - де вам абсолютно потрібна незмінність, або вам потрібно запустити якусь подію, коли змінна встановлюється, або ви хочете скинути виняток із змінної зміни, оскільки вона встановлює стан об'єкта на щось неприємне. Тоді ви заважаєте незайвим вибору між захаращуванням коду яким-небудь спеціальним методом скрізь, на який змінна безпосередньо посилається, має спеціальну форму доступу для 3 з 1000 змінних у вашій програмі.

І це в найкращому випадку сценарій роботи повністю в автономному приватному проекті. Коли ви експортуєте все це до публічно доступної бібліотеки, цих проблем стане ще більше.

Java дуже багатослівна, і це дуже спокусливо зробити. Не робіть цього.


Відмінне обговорення проблем сходження дороги громадських полів. Очевидний недолік Java, який дратує мене, коли мені доводиться переходити на Яву з C # (що дізнався з незручностей Java тут).
ToolmakerSteve

4

Якщо шлях Java - це вихідний шлях, то так, створення класу з загальнодоступними полями порушує принципи приховування інформації, яка говорить про те, що об'єкт повинен керувати власним внутрішнім станом. (Отже, оскільки я не просто розкидаю жаргон на вас, користь від приховування інформації полягає в тому, що внутрішня робота класу прихована за інтерфейсом - скажімо, ви хотіли змінити механізм, завдяки якому ваш клас класу зберег одне із своїх полів, вам, ймовірно, потрібно буде повернутися назад і змінити будь-які класи, які використовують клас ...)

Ви також не можете скористатися підтримкою сумісних класів JavaBean, що зашкодить, якщо ви вирішите, скажімо, використовувати клас на сторінці JavaServer, написану за допомогою мови виразів.

Стаття JavaWorld Чому методи Getter і Setter - це зло також може зацікавити вас при роздумах про те, коли не застосовувати методи доступу та мутаторів.

Якщо ви пишете невелике рішення і хочете мінімізувати кількість коду, що займається, шлях Java може виявитися не правильним способом - я думаю, це завжди залежить від вас і проблеми, яку ви намагаєтеся вирішити.


1
+1 за посиланням на статтю "Чому методи Геттера та Сетера є злими". Однак ваша відповідь була б чіткішою, якби ви вказали, що БОТИ загальнодоступні поля та громадські геттери / сетери РІВНО НЕ ЯВИЙ спосіб: Як пояснено в цій статті - коли це можливо, не робіть жодного з них. Натомість надайте клієнтам методи, специфічні для того, що їм потрібно робити, а не відображати внутрішнє представлення екземпляра. ЗАРАЗ, це насправді не стосується питання, що задається (що використовувати для простого "структура" випадку), на що краще відповідати developer.g, izb та Brian.
ToolmakerSteve

3

Немає нічого поганого в такому типі коду за умови, що автор знає, що вони є структурами (або човниками даних) замість об'єктів. Багато розробників Java не можуть визначити різницю між добре сформованим об'єктом (не лише підкласом java.lang.Object, а справжнім об’єктом у певній області) та ананасом. Ерго, вони закінчують писати структури, коли їм потрібні об'єкти і навпаки.


ананас змушує мене сміятися :)
Гійом

Однак ця відповідь нічого не говорить про те, в чому полягає ця різниця. Набір некваліфікованих розробників не допомагає розробникам знати, коли створити структуру та коли створити клас.
ToolmakerSteve

Це нічого не говорить про різницю, оскільки їхній автор знає про різницю (він знає, що таке структурна структура). Автор запитує, чи використовуються структури в мові ОО, і я кажу так (залежно від проблемного домену.) Якщо питання стосувалося того, що робить об'єкт реальним об'єктом домену, то у вас буде нога, щоб стояти у вашому аргумент.
luis.espinal

Крім того, єдиним типом некваліфікованого розробника, який не повинен знати різниці, був би той, який ще є в школі. Це надзвичайно фундаментально, як знання різниці між пов'язаним списком та хеш-таблицею. Якщо людина закінчує 4-річну ступінь програмного забезпечення, не знаючи, що є справжнім об'єктом, то або ця людина не перешкоджає цій кар'єрі, або він повинен повернутися до школи і вимагати повернення коштів. Я серйозно.
luis.espinal

Але для задоволення вашої скарги я надам відповідь (яка мало стосується оригінального запитання і яка заслуговує на власну тему). Об'єкти мають поведінку та стан інкапсуляції. Конструкцій немає. Об’єктами є державні машини. Структури призначені лише для агрегування даних. Якщо люди хочуть більш детальної відповіді, вони вільні створити нове запитання, де ми можемо детальніше розглянути його до змісту серця.
luis.espinal

2

Проблема з використанням доступу до публічного поля є тією ж проблемою, що і з використанням нового замість фабричного методу - якщо ви згодом передумаєте, усі існуючі абоненти порушені. Отже, з точки зору еволюції API, зазвичай, це гарна ідея кусати кулю та використовувати геттери / сетери.

Одне місце, куди я йду іншим шляхом, - коли ви сильно контролюєте доступ до класу, наприклад, у внутрішньому статичному класі, який використовується як внутрішня структура даних. У цьому випадку може бути набагато зрозуміліше використовувати доступ до поля.

До речі, за твердженням e-bartek, IMO малоймовірно, що підтримка власності буде додана в Java 7.


1
Це правда, але якщо ви використовуєте Java, це не викликає особливих проблем, оскільки ви можете переробити цілу базу коду за один клік (Eclipse, Netbeans, можливо, VIM та Emacs). Якщо ви вибрали одного з його динамічних друзів, як-от Groovy, навіть проста інкапсуляція може зафіксувати вас годинами чи днями. На щастя, у вас були б ваші тестові випадки, які б повідомили вас ... скільки ще коду потрібно виправити.
Дан Розенстарк

2
Ви, звичайно, припускаєте, що всі користувачі знаходяться у вашій кодовій базі, але, звичайно, це часто не відповідає дійсності. Часто навіть з різних нетехнічних причин неможливо змінити код, який може бути у вашій власній базі коду.
Алекс Міллер

2

Я часто використовую цей зразок під час створення приватних внутрішніх класів для спрощення коду, але я б не рекомендував виставляти такі об'єкти в публічному API. Взагалі, чим частіше ви можете зробити об’єкти у вашому загальнодоступному API незмінним, тим краще, і неможливо побудувати ваш "структуроподібний" об'єкт незмінним способом.

Як убік, навіть якби я писав цей об’єкт як приватний внутрішній клас, я все-таки надав конструктор для спрощення коду для ініціалізації об'єкта. Необхідно мати 3 рядки коду, щоб отримати корисний об'єкт, коли це робити, просто безладно.


2

Дуже-дуже старе питання, але дозвольте зробити ще один короткий внесок. Java 8 представила лямбда-вирази та посилання на метод. Лямбда-вирази можуть бути простими посиланнями методів і не оголошувати "справжнє" тіло. Але ви не можете "перетворити" поле в посилання на метод. Таким чином

stream.mapToInt(SomeData1::x)

не законно, але

stream.mapToInt(SomeData2::getX)

є.


У цьому випадку ви можете скористатися data -> data.x, що все-таки розумно
Джеймс Краус

1

Я не бачу шкоди, якщо ти знаєш, що це завжди буде простою структурою і що ти ніколи не захочеш прив’язувати до неї поведінку.


1

Це питання щодо об'єктно-орієнтованого дизайну, а не мови Java. Як правило, добре приховувати типи даних у класі та викривати лише методи, що входять до API класу. Якщо ви відкриєте внутрішні типи даних, ви ніколи не зможете їх змінити в майбутньому. Якщо ви їх приховуєте, ваше єдине зобов'язання перед користувачем - це тип повернення та аргументи методу.


1

Тут я створюю програму для введення Імені та Віку 5 різних осіб та виконую сортування (за віком). Я використовував клас, який виступає як структура (як мова програмування C) і основний клас для виконання повної операції. Далі я надаю код ...

import java.io.*;

class NameList {
    String name;
    int age;
}

class StructNameAge {
    public static void main(String [] args) throws IOException {

        NameList nl[]=new NameList[5]; // Create new radix of the structure NameList into 'nl' object
        NameList temp=new NameList(); // Create a temporary object of the structure

        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

        /* Enter data into each radix of 'nl' object */

        for(int i=0; i<5; i++) {
            nl[i]=new NameList(); // Assign the structure into each radix

            System.out.print("Name: ");
            nl[i].name=br.readLine();

            System.out.print("Age: ");
            nl[i].age=Integer.parseInt(br.readLine());

            System.out.println();
        }

        /* Perform the sort (Selection Sort Method) */

        for(int i=0; i<4; i++) {
            for(int j=i+1; j<5; j++) {
                if(nl[i].age>nl[j].age) {
                    temp=nl[i];
                    nl[i]=nl[j];
                    nl[j]=temp;
                }
            }
        }

        /* Print each radix stored in 'nl' object */

        for(int i=0; i<5; i++)
            System.out.println(nl[i].name+" ("+nl[i].age+")");
    }
}

Вищевказаний код - Помилка вільна та перевірена ... Просто скопіюйте та вставте її у свій IDE і ... Ви знаєте і що ??? :)


0

Ви можете створити простий клас із загальнодоступними полями та без методів у Java, але це все-таки клас і все ще обробляється синтаксично та з точки зору розподілу пам'яті так само, як клас. Немає можливості по-справжньому відтворити структури на Java.


0

Колись я використовую такий клас, коли мені потрібно повернути кілька значень методу. Звичайно, такий об’єкт недовговічний і з дуже обмеженою видимістю, тому він повинен бути нормальним.


0

Як і в більшості речей, існує загальне правило, і тоді існують конкретні обставини. Якщо ви робите закрите, захоплене додаток, щоб ви знали, як даний об’єкт буде використовуватися, ви можете користуватися більшою свободою для сприяння видимості та / або ефективності. Якщо ви розробляєте клас, який публічно використовуватимуть інші, що не є вашим контролем, то нахиліться до моделі getter / setter. Як і у всіх речах, просто використовуйте здоровий глузд. Часто нормально робити початковий раунд з паблік, а потім змінити їх на геттер / сеттерів пізніше.


0

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

Таким чином, ви починаєте з неперехоплених полів з правильним класифікатором доступу. По мірі того, як ваші програмні вимоги зростають, ви додаєте логіку, щоб можливо перевірити, зробити копію повернутого об'єкта тощо.

Філософія геттера / сеттера накладає витрати на велику кількість простих випадків, коли вони не потрібні.

Будь аспектний стиль чистіший чи ні - це дещо якісний. Мені буде легко бачити лише змінні в класі та переглядати логіку окремо. Насправді, основна причина програмування, орієнтованого на Apect, полягає в тому, що багато проблем пов'язані з наскрізними, і їх розділення в тілі класу саме по собі не є ідеальним (реєстрація є прикладом - якщо ви хочете реєструвати все, що отримує Java хоче, щоб ви напишіть цілу купу гетерів і підтримуйте їх синхронізуючи, але AspectJ дозволяє однолінійний).

Проблема ІДЕ - це оселедець. Це не стільки набір тексту, скільки саме читання та візуальне забруднення, що виникає в результаті отримання / набору.

Анотації здаються схожими на аспект-орієнтоване програмування на перший погляд, однак вони вимагають, щоб ви вичерпно перерахували точкові надрізи, додаючи анотації, на відміну від стислої специфікації, що нагадує підказку в AspectJ.

Я сподіваюся, що обізнаність щодо AspectJ заважає людям передчасно зупинятися на динамічних мовах.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.