2010-02-20 3 views
47

나는 그것의 인수로 TextBox 개체를 가진 단일 인수 생성자를 가진 클래스 Base가 있다고 가정합니다. 나는 다음과 같은 형식의 간단한 클래스가있는 경우 :생성자에서 super()보다 먼저 계산을 수행 할 수 있습니까?

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? 
    } 
} 

나는 슈퍼에 대한 호출이 생성자의 첫 번째 호출해야 내게 말하는 오류가 발생합니다. 그러나 이상하게도 나는 이것을 할 수있다.

public class Simple extends Base { 
    public Simple(){ 
    super(new TextBox()); 
    } 
} 

왜 이것이 허용되었지만 첫 번째 예가 아닌가? 먼저 하위 클래스를 설정해야한다는 것을 이해할 수 있으며 수퍼 생성자가 호출되기 전에 객체 변수가 인스턴스화되는 것을 허용하지 않을 수도 있습니다. 그러나 t는 분명히 메소드 (로컬) 변수이므로 허용하지 않는 이유는 무엇입니까?

이 제한 사항을 해결할 수있는 방법이 있습니까? 수퍼바이저를 호출하기 전에 생성자에 입력 한 후에 변수를 보관할 수있는 안전하고 안전한 방법이 있습니까? 또는 더 일반적으로 super가 실제로 호출되기 전에 계산이 완료되도록하지만 생성자 내에서 계산을 허용합니까?

감사합니다.

+2

이것을 가지고 가능한 어떤 이유 gwt로 태그되었습니다? 당신이 gwt에서 그것을 시도했기 때문에 ?? –

+2

TextBox는 GWT 클래스 였지만 아니요, 제가 생각하기에는 관련이 없습니다. –

답변

54

예, 간단한 경우에 대한 해결책이 있습니다. 인수로 TextBox을 가져 와서 공용 생성자에서 호출하는 전용 생성자를 만들 수 있습니다.

public class Simple extends Base { 
    private Simple(TextBox t) { 
     super(t); 
     // continue doing stuff with t here 
    } 

    public Simple() { 
     this(new TextBox()); 
    } 
} 

더 복잡한 경우에는 팩토리 또는 정적 팩터 리 메서드를 사용해야합니다.

+1

이것은 생성 후에 생성 된 객체에 대한 참조를 어떻게 사용할지에 대한 질문에 대한 좋은 대답 인 것처럼 보입니다. –

+2

이것은 매우 편리한 패턴이며,'super()'가 생성자의 다른 요소 다음에 나타나지 않는다는 요구를 완전히 피할 수있게 해줍니다. 극단적 인 경우에는 여러 사설 생성자를 함께 연결할 수도 있습니다.하지만 내가해야 할 상황을 생각할 수는 없으며, 만약 그렇게했다면 내가 수행 할 수있는 더 나은 방법이 있는지 궁금해지기 시작할 것입니다. 하고 있었다. –

+0

예. 다른 사람들은 이미 Java에서 이와 같은 방식으로 작동한다고 대답했습니다. 특정 해결 방법을 지적하고 싶습니다. 나는 대부분의 _valid_ 사례를 생각 해낼 수 있다고 생각합니다. 또한 가능한 해결 방법을 찾는 것도 가능합니다. 이제는 내 자신과 모순되게,이 비트가 나에게 한 가지 사례가 있습니다. 클래스의 생성자에 Class 매개 변수가있는 클래스를 확장하려고했습니다. 나는'super (this.getClass()) '를 호출하고 싶었지만, 당신이'this'를 참조하도록 허용되지 않았으므로,이 코드는 실제 클래스를 알 수 있어야한다는 것이 완전히 합리적이라고 생각하더라도 불법입니다. 포인트. – waxwing

0

두 번째 예가 허용되지만 첫 번째가 허용되지 않는 이유는 언어를 깔끔하게 유지하고 이상한 규칙을 도입하지 않을 가능성이 높기 때문입니다. 당신이 초기화되어 있어야하지만 여전히 없었던 것들로 엉망 수도 있기 때문에 호출 된 슈퍼 위험 할 것 전에 코드를 실행하도록 허용

. 기본적으로, 당신은 수퍼 자체에 대한 호출 (예 : 생성자에 가야하는 몇 가지 물건을 계산하기위한 정적 메서드 호출)에서 많은 것들을 할 수 있다고 생각하지만, 당신은 아무것도에서 사용할 수 없을거야 - 좋은 것 인 완전하게 구성된 물체.

7

수퍼 클래스가 안정적으로 생성되도록 보장하기 위해 required입니다. 첫 번째. 특히 "생성자가 명시 적으로 수퍼 클래스 생성자를 호출하지 않으면 Java 컴파일러는 수퍼 클래스의 인수없는 생성자에 대한 호출을 자동으로 삽입합니다." 당신의 예에서

는 슈퍼 클래스는 건설시 t의 상태에 의존 할 수있다. 나중에 사본을 요청할 수 있습니다.

는 광범위한 토론 herehere있다.

+2

흥미롭게도, 수퍼 클래스 생성자 호출을 둘러싼 코드를 래핑하는 것이 유용 할 수있는 가장 중요한 경우 중 하나를 방지하기 위해 Java가 중단되는 것처럼 들리지만, 생성자가 예외를 throw하면 모든 것이 정리 될 수 있습니다. 예를 들어, 오브젝트 생성자 오버로드 중 하나가 전달 된 파일에서 데이터를 읽는 경우, 파생 클래스 생성자는 파일 이름을 허용하는 오버로드를 갖고, 상위 클래스 생성자에 새로 열린 파일을 전달한 다음 파일을 닫을 수 있습니다 기후. 수퍼 클래스 생성자가 throw하는 경우 어떻게 파일을 닫을 수 있습니까? – supercat

+0

@supercat : 상속을 위해 디자인하거나 배제해야합니다 [Bloch, * EffectiveJava *, §17]; 이 [Q & A] (http://stackoverflow.com/q/1371369/230513)도 참조하십시오. – trashgod

+0

서브 클래스 객체의 생성에 "리소스 확보, 수퍼 클래스 객체 생성, 리소스 해제"패턴이 필요한 경우 어떻게 구현해야합니까? 내부 생성자를 실패시 사용할 단일 인터페이스 메서드를 구현하는 객체에 전달 하시겠습니까? 약간의 추가 호출자 레벨 연결을 희생시키면서 막연하게 실행 가능합니다. – supercat

0

Java가 작동하는 방식 :-)이 방법을 선택한 이유는 기술적 인 이유가 있습니다. super를 호출하기 전에 지역 주민들의 계산을 할 수 없다는 것은 이상 할 것입니다.하지만 Java에서는 먼저 객체를 할당해야하므로 실수로 수정하기 전에 모든 필드를 올바르게 초기화해야합니다. 그들. 귀하의 경우에는

은 당신이 슈퍼에 준 매개 변수를()에 액세스 할 수있는 게터 대부분의 시간이있다. 따라서 다음을 사용하십시오.

 
super(new TextBox()); 
final TextBox box = getWidget(); 
... do your thing... 
+2

슈퍼 클래스 생성자가 서브 클래스가 오버라이드 (override)하지 않는'final' 인스턴스 메소드를 호출 할 수 있기 때문에 "모든 필드가 올바르게 초기화되었습니다"는 Java에서는 실제로 보장되지 않습니다 (IIUC, C++과 다름). 재정의하면 하위 클래스의 초기화 된 필드가 표시되지 않습니다 (인스턴스 초기화 프로그램이있는 '최종'필드조차도!). 일부 정적 분석 도구는이 상황에 대해 경고합니다. –

17

슈퍼 콜하기 전에 계산에 동일한 문제가있었습니다. 때로는 super()에 전화하기 전에 몇 가지 조건을 확인하려고합니다. 예를 들어, 만들 때 많은 리소스를 사용하는 클래스가 있습니다. 하위 클래스는 몇 가지 추가 데이터를 원하며 수퍼 생성자를 호출하기 전에 먼저이를 확인하려고 할 수 있습니다. 이 문제를 해결하는 간단한 방법이 있습니다. 조금 이상한 보이지만, 그것은 잘 작동 될 수 있습니다

는 슈퍼 생성자의 인수를 리턴 클래스 내부의 개인 정적 방법을 사용하고 내부 수표를합니다

public class Simple extends Base { 
    public Simple(){ 
    super(createTextBox()); 
    } 

    private static TextBox createTextBox() { 
    TextBox t = new TextBox(); 
    t.doSomething(); 
    // ... or more 
    return t; 
    } 
} 
관련 문제