Названная идиома Параметра в Java

Как реализовать Названный идиомой Параметра в Java? (специально для конструкторов)

Я ищу Objective C как синтаксис и не как тот, используемый в JavaBeans.

Небольшой пример кода был бы прекрасен.

Спасибо.

71
задан Red Hyena 1 January 2010 в 06:18
поделиться

5 ответов

Лучшей Java-идиомой для моделирования аргументов ключевых слов в конструкторах, на мой взгляд, является паттерн Builder, описанный в Effective Java 2nd Edition.

Основная идея заключается в том, чтобы иметь класс Builder, который имеет setters (но, как правило, не getters) для различных параметров конструктора. Также существует метод build(). Класс Builder часто является (статическим) вложенным классом класса, который он использует для сборки. Конструктор внешнего класса часто является приватным.

Конечный результат выглядит как:

public class Foo {
  public static class Builder {
    public Foo build() {
      return new Foo(this);
    }

    public Builder setSize(int size) {
      this.size = size;
      return this;
    }

    public Builder setColor(Color color) {
      this.color = color;
      return this;
    }

    public Builder setName(String name) {
      this.name = name;
      return this;
    }

    // you can set defaults for these here
    private int size;
    private Color color;
    private String name;
  }

  public static Builder builder() {
      return new Builder();
  }

  private Foo(Builder builder) {
    size = builder.size;
    color = builder.color;
    name = builder.name;
  }

  private final int size;
  private final Color color;
  private final String name;

  // The rest of Foo goes here...
}

Для создания экземпляра Foo нужно написать что-то вроде:

Foo foo = Foo.builder()
    .setColor(red)
    .setName("Fred")
    .setSize(42)
    .build();

Главное предостережение:

  1. Установка паттерна довольно многословна (как вы видите). Наверное, это того не стоит, за исключением классов, которые вы планируете инстанцировать во многих местах.
  2. Нет никакой проверки времени компиляции, что все параметры были указаны ровно один раз. Вы можете добавить проверку во время выполнения, или вы можете использовать это только для опциональных параметров и сделать требуемые параметры нормальными либо для Foo, либо для конструктора Строителя. (Обычно людей не волнует случай, когда один и тот же параметр задается несколько раз.)

Вы также можете захотеть посмотреть этот пост в блоге (не я).

.
94
ответ дан 24 November 2019 в 12:48
поделиться

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

public class Something {

    String name;
    int size; 
    float weight;

    public Something(String name, int size, float weight) {
        this.name = name;
        this.size = size;
        this.weight = weight;
    }

    public static String name(String name) { 
        return name; 
    }

    public static int size(int size) {
        return size;
    }

    public float weight(float weight) {
        return weight;
    }

}

Использование:

import static Something.*;

Something s = new Something(name("pen"), size(20), weight(8.2));

Ограничения по сравнению с реальными именованными параметрами:

  • порядок следования аргументов релевантен
  • списки переменных аргументов невозможны с помощью одного конструктора
  • вам нужен метод для каждого аргумента
  • не лучше, чем комментарий (new Something(/*name*/ "ручка", /*size*/ 20, /*weight*/ 8). 2))

Если у вас есть выбор, посмотрите на Scala 2.8. http://www.scala-lang.org/node/2075

2
ответ дан 24 November 2019 в 12:48
поделиться

Вот небольшая вариация техники, приведенная в "Эффективной Яве" Иешуа Блоха. Здесь я попытался сделать клиентский код более читабельным (или, возможно, более DSLish).

/**
 * Actual class for which we want to implement a 
 * named-parameter pseudo-constructor
 */
class Window{
    protected int x, y, width, height;
    protected boolean isResizable;
    protected String title;

    public void show(){
        // Show the window
        System.out.printf("Window \"%s\" set visible.%n",title);
    }

    /**
     * This class is only used to set the parameter values
     */
    static class HavingProperties extends Window{

        public HavingProperties x(int value){
            this.x=value;
            return this;
        }

        public HavingProperties y(int value){
            this.y=value;
            return this;
        }

        public HavingProperties width(int value){
            this.width=value;
            return this;
        }

        public HavingProperties height(int value){
            this.height=value;
            return this;
        }

        public HavingProperties resizable(boolean value){
            this.isResizable=value;
            return this;
        }

        public HavingProperties title(String value){
            this.title=value;
            return this;
        }
    }
}

public class NamedParameterIdiomInAction {
    public static void main(String... args){
        Window window=new Window.HavingProperties().x(10).y(10).width(100).
                height(100).resizable(true).title("My App");
        window.show();
    }
}

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

7
ответ дан 24 November 2019 в 12:48
поделиться

Стоит упомянуть:

Foo foo = new Foo() {{
    color = red;
    name = "Fred";
    size = 42;
}};

так называемый инициализатор двойной браузеры. На самом деле это анонимный класс с инициализатором экземпляра.

66
ответ дан 24 November 2019 в 12:48
поделиться

Java не поддерживает именованные параметры типа Objective-C для конструкторов или аргументов методов. Более того, на самом деле это не Java-способ делать вещи. В java типичный шаблон - многословно именованные классы и члены. Классы и переменные должны быть существительными, а именованный метод - глаголами. Я полагаю, что вы могли бы проявить творческий подход и отклониться от соглашений об именовании на Java и подражать парадигме Objective-C, но это не было бы особенно ценным для среднего Java-разработчика, которому поручено сопровождение вашего кода. Работая на любом языке, вы должны придерживаться конвенций языка и сообщества, особенно при работе в команде.

6
ответ дан 24 November 2019 в 12:48
поделиться
Другие вопросы по тегам:

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