Java에서 Named Parameter 관용구를 구현하는 방법은 무엇입니까? (특히 생성자)
JavaBeans에서 사용되는 구문이 아닌 Objective-C와 같은 구문을 찾고 있습니다.
작은 코드 예제가 좋습니다.
감사.
답변
생성자에서 키워드 인수를 시뮬레이션하기 위해 내가 본 최고의 Java 관용구는 Effective Java 2nd Edition에 설명 된 Builder 패턴 입니다.
기본 아이디어는 다른 생성자 매개 변수에 대한 setter (일반적으로 getter가 아님)가있는 Builder 클래스를 갖는 것입니다. 도있다 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();
주요주의 사항은 다음과 같습니다.
- 패턴 설정은 매우 장황합니다 (보시다시피). 많은 곳에서 인스턴스화하려는 클래스를 제외하고는 그만한 가치가 없을 것입니다.
- 모든 매개 변수가 정확히 한 번 지정되었는지 컴파일 타임 검사가 없습니다. 런타임 검사를 추가하거나 선택적 매개 변수에만 이것을 사용하고 필수 매개 변수를 Foo 또는 Builder의 생성자에 일반 매개 변수로 만들 수 있습니다. (사람들은 일반적으로 동일한 매개 변수가 여러 번 설정되는 경우에 대해 걱정하지 않습니다.)
이 블로그 게시물 (내가 아님) 도 확인하실 수 있습니다 .
답변
이것은 언급 할 가치가 있습니다.
Foo foo = new Foo() {{
color = red;
name = "Fred";
size = 42;
}};
소위 이중 중괄호 이니셜 라이저 . 실제로 인스턴스 이니셜 라이저가있는 익명 클래스입니다.
답변
여기에서 조언을 따를 수도 있습니다 :
http://www.artima.com/weblogs/viewpost.jsp?thread=118828
int value; int location; boolean overwrite;
doIt(value=13, location=47, overwrite=true);
호출 사이트에서는 장황하지만 전반적으로 오버 헤드가 가장 낮습니다.
답변
자바 8 스타일 :
public class Person {
String name;
int age;
private Person(String name, int age) {
this.name = name;
this.age = age;
}
static PersonWaitingForName create() {
return name -> age -> new Person(name, age);
}
static interface PersonWaitingForName {
PersonWaitingForAge name(String name);
}
static interface PersonWaitingForAge {
Person age(int age);
}
public static void main(String[] args) {
Person charlotte = Person.create()
.name("Charlotte")
.age(25);
}
}
- 명명 된 매개 변수
- 인수 순서 수정
- 정적 검사-> 이름없는 사람이 불가능합니다.
- 같은 유형의 인수를 우연히 전환하기가 어렵습니다 (텔레 스코프 생성자에서 가능한 것처럼)
답변
Java는 생성자 또는 메소드 인수에 대해 Objective-C와 유사한 명명 된 매개 변수를 지원하지 않습니다. 게다가 이것은 실제로 Java 방식이 아닙니다. Java에서 일반적인 패턴은 자세한 이름이 지정된 클래스 및 멤버입니다. 클래스와 변수는 명사 여야하고 명명 된 메서드는 동사 여야합니다. 나는 당신이 창의력을 발휘하고 Java 명명 규칙에서 벗어날 수 있고 해키 방식으로 Objective-C 패러다임을 에뮬레이션 할 수 있다고 생각하지만 이것은 코드 유지 관리를 담당하는 평균 Java 개발자가 특별히 높이 평가하지 않을 것입니다. 어떤 언어로 작업 할 때 특히 팀에서 작업 할 때 언어 및 커뮤니티의 관습을 고수해야합니다.
답변
Java 6을 사용하는 경우 변수 매개 변수를 사용하고 정적을 가져 와서 훨씬 더 나은 결과를 생성 할 수 있습니다. 이에 대한 자세한 내용은 다음에서 찾을 수 있습니다.
http://zinzel.blogspot.com/2010/07/creating-methods-with-named-parameters.html
요컨대, 다음과 같은 것을 가질 수 있습니다.
go();
go(min(0));
go(min(0), max(100));
go(max(100), min(0));
go(prompt("Enter a value"), min(0), max(100));
답변
이 스타일은 다른 언어에있는 get 및 set 접두사 없이 명명 된 매개 변수 와 속성 기능을 모두 처리한다는 점을 지적하고 싶습니다 . Java 영역에서는 일반적이지 않지만 특히 다른 언어를 처리 한 경우 이해하기 어렵지 않고 더 간단합니다.
public class Person {
String name;
int age;
// name property
// getter
public String name() { return name; }
// setter
public Person name(String val) {
name = val;
return this;
}
// age property
// getter
public int age() { return age; }
// setter
public Person age(int val) {
age = val;
return this;
}
public static void main(String[] args) {
// Addresses named parameter
Person jacobi = new Person().name("Jacobi").age(3);
// Addresses property style
println(jacobi.name());
println(jacobi.age());
//...
jacobi.name("Lemuel Jacobi");
jacobi.age(4);
println(jacobi.name());
println(jacobi.age());
}
}