Как реализовать Названный идиомой Параметра в Java? (специально для конструкторов)
Я ищу Objective C как синтаксис и не как тот, используемый в JavaBeans.
Небольшой пример кода был бы прекрасен.
Спасибо.
Лучшей 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();
Главное предостережение:
Вы также можете захотеть посмотреть этот пост в блоге (не я).
.Можно использовать обычный конструктор и статические методы, которые дают аргументам имя:
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));
Ограничения по сравнению с реальными именованными параметрами:
/*name*/ "ручка", /*size*/ 20, /*weight*/ 8). 2)
)Если у вас есть выбор, посмотрите на Scala 2.8. http://www.scala-lang.org/node/2075
Вот небольшая вариация техники, приведенная в "Эффективной Яве" Иешуа Блоха. Здесь я попытался сделать клиентский код более читабельным (или, возможно, более 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();
}
}
Пожалуйста, обратите внимание, что с этой вариацией вы также можете давать осмысленные имена вашим псевдоконструкторам.
Стоит упомянуть:
Foo foo = new Foo() {{
color = red;
name = "Fred";
size = 42;
}};
так называемый инициализатор двойной браузеры. На самом деле это анонимный класс с инициализатором экземпляра.
Java не поддерживает именованные параметры типа Objective-C для конструкторов или аргументов методов. Более того, на самом деле это не Java-способ делать вещи. В java типичный шаблон - многословно именованные классы и члены. Классы и переменные должны быть существительными, а именованный метод - глаголами. Я полагаю, что вы могли бы проявить творческий подход и отклониться от соглашений об именовании на Java и подражать парадигме Objective-C, но это не было бы особенно ценным для среднего Java-разработчика, которому поручено сопровождение вашего кода. Работая на любом языке, вы должны придерживаться конвенций языка и сообщества, особенно при работе в команде.