본문 바로가기
expert

Dart에서 멤버 변수가 초기화되는 방식에 차이가 있습니까?

by RWriter 2023. 1. 24.
반응형

질문 제목:

Dart에서 멤버 변수가 초기화되는 방식에 차이가 있습니까?

질문 내용:

Dart에서 값을 바로 할당하는 것과 Java와 같은 생성자에서 차이가 있습니까?

class Example {
    int x = 3;
}

class Example {
    int x;
    Example() {
        x = 3;
    }
}

제가 Flutter를 사용하면서 setState를 사용하는 Function을 변수에 할당하려고 했을 때 전자의 방법으로는 불가능했지만 후자의 방법으로는 가능했기 때문에 질문드립니다.

해결 답변:

귀하의 사소한 경우에는 중요하지 않습니다.일반적으로 다음과 같은 몇 가지 방법으로 인스턴스 변수를 초기화할 수 있습니다.

인라인(필드 이니셜라이저)

class Example1 {
  T x = value;
}

이점:

  • 직접적이고 간결합니다.
  • 멤버는 모든 생성자에서 초기화됩니다.
  • 멤버 를 초기화 final하거나 null을 허용하지 않는 데 사용할 수 있습니다.
  • Member는 기본 클래스 생성자를 호출하기 전에 초기화되며 이는 기본 클래스 생성자가 파생 클래스에 의해 재정의된 멤버 함수를 호출할 때 중요합니다.

단점:

이니셜라이저 목록

class Example2 {
  T x;

  Example2() : x = value;
}

이점:

  • 멤버 를 초기화 final하거나 null을 허용하지 않는 데 사용할 수 있습니다.
  • Member는 기본 클래스 생성자를 호출하기 전에 초기화되며 이는 기본 클래스 생성자가 파생 클래스에 의해 재정의된 멤버 함수를 호출할 때 중요합니다.
  • 구성 인수를 활용할 수 있습니다.
  • 초기화된 변수 는 항상 멤버 변수를 참조하며 결코 생성자 매개변수를 참조하지 않습니다.

단점:

  • 클래스에 여러 생성자가 있는 경우 초기화를 복제하거나 생성자를 공통 생성자로 리디렉션해야 합니다.
  • this유효해 지기 전에 초기화가 발생하기 때문에 의존할 수 없습니다 this(즉, 다른 인스턴스 멤버에 의존할 수 없음).
  • 바깥쪽 클래스의 멤버만 초기화할 수 있습니다. 이니셜라이저 목록은 기본 클래스 생성자를 호출하기 전에 실행되기 때문에 기본 클래스 멤버를 설정할 수 없습니다.

생성자 본체

class Example3 {
  T x;

  Example3() {
    x = value;
  } 
}

이점:

  • 구성 인수를 활용할 수 있습니다.
  • 단일 표현식을 통해 멤버를 초기화할 수 없는 경우와 같이 더 복잡한 초기화를 수행하는 데 사용할 수 있습니다.
  • 사용할 수 있습니다 this(즉, 다른 인스턴스 구성원을 사용할 수 있음).
  • 기본 클래스 멤버를 설정하는 데 사용할 수 있습니다.

단점:

  • late finalnull을 허용하지 않거나 null을 허용하지 않는 멤버 를 초기화하는 데 사용할 수 없습니다 .
  • 클래스에 생성자가 여러 개 있는 경우 초기화를 복제하거나 초기화 코드를 리팩토링해야 합니다(예: 공통 생성자로 리디렉션).
  • 멤버는 기본 클래스 생성자를 호출 한 후 초기화됩니다.
  • 생성자에 멤버 변수를 가리는 매개변수가 있는 경우 실수로 멤버 대신 매개변수를 참조하기 쉽습니다. (자세한 내용은 https://github.com/dart-lang/linter/issues/2552 를 참조하세요.)

제가 잊고 있는 몇 가지 사항이 있을 수 있지만 주요 사항을 다루어야 한다고 생각합니다.직접 인라인 초기화가 먼저 발생한 다음 초기화 목록, 생성자 본문 순으로 발생합니다. 또한 개체 초기화의 나중 단계에서만 유효한 이유를 설명하는

매개 변수 목록의 값 할당과 이니셜라이저 목록의 차이점을 참조하십시오.

 

this

멤버가 초기화되는 위치가 중요한 예를 들면 다음과 같습니다.

class Base {
  Base() {
    doSomething();
  }

  void doSomething() {}
}

class DerivedEarly extends Base {
  int? x;

  DerivedEarly() : x = 42;

  @override
  void doSomething() => print(x);
}

class DerivedLate extends Base {
  int? x;

  DerivedLate() {
    x = 42;
  }

  @override
  void doSomething() => print(x);
}

void main() {
  DerivedEarly(); // Prints: 42
  DerivedLate(); // Prints: null
}
반응형

댓글