Programing

생성자에서 super () 전에 계산을 수행 할 수 있습니까?

lottogame 2020. 11. 28. 08:33
반응형

생성자에서 super () 전에 계산을 수행 할 수 있습니까?


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

It is required by the language in order to ensure that the superclass is reliably constructed first. In particular, "If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass."

In your example, the superclass may rely on the state of t at construction time. You can always ask for a copy later.

There's an extensive discussion here and here.


The reason why the second example is allowed but not the first is most likely to keep the language tidy and not introduce strange rules.

Allowing any code to run before super has been called would be dangerous since you might mess with things that should have been initialized but still haven't been. Basically, I guess you can do quite a lot of things in the call to super itself (e.g. call a static method for calculating some stuff that needs to go to the constructor), but you'll never be able to use anything from the not-yet-completely-constructed object which is a good thing.


That's how Java works :-) There are technical reasons why it was chosen this way. It might indeed be odd that you can not do computations on locals before calling super, but in Java the object must first be allocated and thus it needs to go all the way up to Object so that all fields are correctly initialized before your could accidently moddify them.

In your case there is most of the time a getter that allows you to access the parameter your gave to super(). So you would use this:

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

You can define a static supplier lambda which can contain more complicated logic.

public class MyClass {

    private static Supplier<MyType> myTypeSupplier = () -> {
        return new MyType();
    };

    public MyClass() {
        super(clientConfig, myTypeSupplier.get());
    }
}

참고URL : https://stackoverflow.com/questions/2303604/is-it-possible-to-do-computation-before-super-in-the-constructor

반응형