Подтвердить что ты не робот

Цепочка методов в Java

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

Если бы я должен был создать класс Car, например, я мог бы сделать его цепным путем повторного использования this вместо void следующим образом:

public class Car {
    private String make;        

    public Car setMake(String make) {
        this.make = make;
        return this;
    }   
}

Есть ли какая-то особая причина, почему встроенные библиотеки не склонны так поступать? Есть ли недостаток в цепочке методов?

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

container.add((new JLabel("label text")).setMaximumSize(new Dimension(100,200)));

а не более длинный: Примечание. Это не помешает вам кодировать этот путь, если вы пожелаете.

JLabel label = new JLabel("label text");
label.setMaximumSize(new Dimension(100,200));
container.add(label);

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

4b9b3361

Ответ 1

Э. Есть аргументы читаемости в обоих направлениях - есть такая вещь, как попытка слишком много вложить в одну строку.

Но, честно говоря, я подозреваю здесь это по историческим причинам: повсеместное "цепное" поведение на самом деле не стало популярным или широко известным, когда, например, Swing развивается. Вы можете утверждать, что это должно было быть добавлено позже, но такие вещи, как правило, создают двоичные несовместимости и другие проблемы, с которыми Sun/Oracle исторически были чрезвычайно осторожны.

Более свежие библиотеки JDK - см., например, ByteBuffer для основного, хорошо известного примера - обеспечили поведение цепочки и т.д., где это имеет смысл.

Ответ 2

Еще одна причина, по которой я могу думать, - это производительность, а точнее: не платите за то, что вы не используете. return this после того, как каждый метод не является очень дорогостоящим, но все же требует нескольких дополнительных циклов процессора и одного реестра ЦП.

Была даже идея добавить неявный return this для каждого метода, объявляющего возвращаемое значение void, но оно было отклонено.

Ответ 3

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

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

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

class Foo {
   Foo chainedMethod() {...}
}

class Bar extends Foo {
   Foo chainedMethod() {...} //had to return Foo for Java versions < 1.5
   void doStuff();
}

Поэтому, когда вы пытаетесь сделать new Bar().chainedMethod().doStuff(), он не будет компилироваться. И ((Bar)new Bar().chainedMethod()).doStuff() выглядит не очень хорошо, делает это:)

Ответ 4

Цепочка метода обычно используется с шаблоном Builder, и вы можете видеть это в классе StringBuilder. Вне этого, цепочка методов может сделать разделение команды и создания менее ясным, например, если repaint() также будет частью свободного интерфейса? Тогда я мог бы:

container.add(label).repaint().setMaximumSize(new Dimension(100,200)));

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

Ответ 5

Причиной отсутствия реализации цепочки методов может быть следующее:

  • Самая большая проблема для метода Chaining - проблема финиша. Хотя есть обходные пути, обычно, если вы столкнетесь с этим, вы лучше использовать вложенную функцию. Вложенные функции также лучше если вы попадаете в беспорядок с переменными контекста.

  • Там нет гарантии, что объект из цепочки действительно вернет действительный, непустой объект. Кроме того, отладка этого стиля кода часто бывает много сложнее, так как многие * IDE * s не будут оценивать вызов метода при отладке время как объект, который вы можете проверить

  • Это может запутаться, когда вы вызываете подпрограммы к другим классам передать аргументы одному из методов цепочки, когда есть много параметров, проходящих в основном потому, что линии очень длинны

  • Также существует проблема с производительностью, которая будет работать в памяти

Ответ 6

Вы действительно спрашиваете о Закон Деметры

"Только поговорите со своими ближайшими друзьями"

Обратите внимание, что вышеупомянутая ссылка - замечательный ресурс, но вы можете потратить там много времени и не получить ответ, который вы искали!: -)