TextBox 개체를 인수로 사용하는 단일 인수 생성자가있는 Base 클래스가 있다고 가정합니다. 다음 형식의 Simple 클래스가있는 경우 :
public class Simple extends Base {
public Simple(){
TextBox t = new TextBox();
super(t);
//wouldn't it be nice if I could do things with t down here?
}
}
super에 대한 호출이 생성자의 첫 번째 호출이어야한다는 오류가 표시됩니다. 그러나 이상하게도 나는 이것을 할 수 있습니다.
public class Simple extends Base {
public Simple(){
super(new TextBox());
}
}
이것이 허용되지만 첫 번째 예는 허용되지 않는 이유는 무엇입니까? 먼저 하위 클래스를 설정해야하고 수퍼 생성자가 호출되기 전에 개체 변수가 인스턴스화되지 않도록해야한다는 것을 이해할 수 있습니다. 하지만 t는 분명히 메서드 (로컬) 변수이므로 허용하지 않는 이유는 무엇입니까?
이 제한을 피할 수있는 방법이 있습니까? super를 호출하기 전에 생성 할 수 있지만 생성자를 입력 한 후에 구성 할 수있는 변수를 유지하는 안전하고 좋은 방법이 있습니까? 또는 더 일반적으로 super가 실제로 호출되기 전에 계산을 수행 할 수 있지만 생성자 내에서 수행 할 수 있습니까?
감사합니다.
답변
예, 간단한 사례에 대한 해결 방법이 있습니다. TextBox
인수로 사용하는 개인 생성자를 만들고 공용 생성자에서 호출 할 수 있습니다.
public class Simple extends Base {
private Simple(TextBox t) {
super(t);
// continue doing stuff with t here
}
public Simple() {
this(new TextBox());
}
}
더 복잡한 작업의 경우 팩토리 또는 정적 팩토리 메서드를 사용해야합니다.
답변
슈퍼 호출 전에 계산에 동일한 문제가있었습니다. 때로는 전화하기 전에 몇 가지 조건을 확인하고 싶을 때super()
. 예를 들어 생성시 많은 리소스를 사용하는 클래스가 있습니다. 하위 클래스는 추가 데이터를 원하며 수퍼 생성자를 호출하기 전에 먼저 데이터를 확인하려고 할 수 있습니다. 이 문제를 해결하는 간단한 방법이 있습니다. 약간 이상하게 보일 수 있지만 잘 작동합니다.
슈퍼 생성자의 인수를 반환하고 내부에서 확인하는 클래스 내부의 비공개 정적 메서드를 사용합니다.
public class Simple extends Base {
public Simple(){
super(createTextBox());
}
private static TextBox createTextBox() {
TextBox t = new TextBox();
t.doSomething();
// ... or more
return t;
}
}
답변
답변
더 복잡한 논리를 포함 할 수있는 정적 공급자 람다를 정의 할 수 있습니다.
public class MyClass {
private static Supplier<MyType> myTypeSupplier = () -> {
return new MyType();
};
public MyClass() {
super(clientConfig, myTypeSupplier.get());
}
}
답변
두 번째 예제는 허용되지만 첫 번째 예제는 허용되지 않는 이유는 언어를 깔끔하게 유지하고 이상한 규칙을 도입하지 않을 가능성이 높습니다.
super가 호출되기 전에 코드가 실행되도록 허용하는 것은 초기화되어야했지만 아직되지 않은 것들을 망칠 수 있기 때문에 위험 할 것입니다. 기본적으로 super 자체에 대한 호출에서 많은 작업을 수행 할 수 있다고 생각합니다 (예 : 생성자로 이동해야하는 일부 항목을 계산하기위한 정적 메서드 호출). 그러나 그렇지 않은 경우에는 아무것도 사용할 수 없습니다. -아직 완전하게 만들어진 물체는 좋은 것입니다.
답변
이것이 자바가 작동하는 방식입니다. :-)이 방식으로 선택된 이유가 있습니다. super를 호출하기 전에 로컬에서 계산을 수행 할 수 없다는 것은 참 이상 할 수 있지만 Java에서는 먼저 객체를 할당해야하므로 실수로 수정하기 전에 모든 필드가 올바르게 초기화되도록 Object까지 계속 이동해야합니다. 그들.
귀하의 경우에는 대부분의 경우 super ()에 부여한 매개 변수에 액세스 할 수있는 게터가 있습니다. 따라서 이것을 사용합니다.
super (new TextBox ()); 최종 텍스트 상자 상자 = getWidget (); ... 당신의 일을 ...
답변
이것은 추가 개체를 만들고 추가 클래스, 필드, 메서드 등을 만들지 않고도 수정할 수있는 내 솔루션입니다.
class TextBox {
}
class Base {
public Base(TextBox textBox) {
}
}
public class Simple extends Base {
public Simple() {
super(((Supplier<TextBox>) () -> {
var textBox = new TextBox();
//some logic with text box
return textBox;
}).get());
}
}