Структурировать как объекты в Java - PullRequest
193 голосов
/ 31 августа 2008

Это полностью противоречит способу 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();
}

Ответы [ 20 ]

2 голосов
/ 10 июля 2014

Очень-очень старый вопрос, но позвольте мне сделать еще один небольшой вклад. Java 8 представила лямбда-выражения и ссылки на методы. Лямбда-выражения могут быть простыми ссылками на методы и не объявлять «истинное» тело. Но вы не можете «преобразовать» поле в ссылку на метод. Таким образом

stream.mapToInt(SomeData1::x)

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

stream.mapToInt(SomeData2::getX)

есть.

2 голосов
/ 15 октября 2008

Я часто использую этот шаблон при создании закрытых внутренних классов, чтобы упростить мой код, но я бы не рекомендовал выставлять такие объекты в публичном API. В общем, чем чаще вы можете сделать объекты в вашем публичном API неизменяемыми, тем лучше, и невозможно создать свой «структурный» объект неизменным образом.

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

2 голосов
/ 15 сентября 2008

Проблема использования доступа к общедоступным полям та же, что и при использовании нового вместо заводского метода - если вы передумаете позже, все существующие вызывающие абоненты будут прерваны. Таким образом, с точки зрения развития API, обычно неплохо кусать пули и использовать методы получения / установки.

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

Кстати, по утверждению e-bartek, очень маловероятно, что IMO будет добавлена ​​поддержка свойств в Java 7.

1 голос
/ 31 августа 2008

Это вопрос об объектно-ориентированном проектировании, а не о языке Java. Обычно рекомендуется скрывать типы данных внутри класса и предоставлять только те методы, которые являются частью API класса. Если вы выставите внутренние типы данных, вы никогда не сможете изменить их в будущем. Если вы их скрываете, ваше единственное обязательство перед пользователем - это методы return и типы аргументов.

1 голос
/ 31 августа 2008

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

1 голос
/ 19 февраля 2013

Здесь я создаю программу для ввода имени и возраста 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 голосов
/ 15 октября 2008

Вы можете создать простой класс с открытыми полями и без методов в Java, но он по-прежнему является классом и по-прежнему обрабатывается синтаксически и с точки зрения распределения памяти, как класс. В Java нет способа действительно воспроизвести структуры.

0 голосов
/ 23 ноября 2008

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

0 голосов
/ 19 декабря 2011

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

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

Философия получения / установки устанавливает затраты на большое количество простых случаев, когда они не нужны.

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

Проблема IDE - красная сельдь. Это не столько печатание, сколько чтение и визуальное загрязнение, возникающее при получении / наборе.

На первый взгляд аннотации похожи на аспектно-ориентированное программирование, однако они требуют от вас исчерпывающего перечисления pointcut, добавляя аннотации, в отличие от краткой спецификации подстановочных знаков в AspectJ.

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

0 голосов
/ 25 апреля 2010

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

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