반응형
질문 제목:
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는 기본 클래스 생성자를 호출하기 전에 초기화되며 이는 기본 클래스 생성자가 파생 클래스에 의해 재정의된 멤버 함수를 호출할 때 중요합니다.
단점:
- 구성 인수에 의존할 수 없습니다.
- 일반적으로
this
초기화는 유효해지기 전에 발생하므로 의존할 수 없습니다this
(즉, 다른 인스턴스 멤버에 의존할 수 없음). ( 단, 멤버를 선언하여 느리게 초기화하는 경우는 예외입니다late
. 이렇게 하려면 null-safety 기능을 활성화해야 합니다.)
이니셜라이저 목록
class Example2 {
T x;
Example2() : x = value;
}
이점:
- 멤버 를 초기화
final
하거나 null을 허용하지 않는 데 사용할 수 있습니다. - Member는 기본 클래스 생성자를 호출하기 전에 초기화되며 이는 기본 클래스 생성자가 파생 클래스에 의해 재정의된 멤버 함수를 호출할 때 중요합니다.
- 구성 인수를 활용할 수 있습니다.
- 초기화된 변수 는 항상 멤버 변수를 참조하며 결코 생성자 매개변수를 참조하지 않습니다.
단점:
- 클래스에 여러 생성자가 있는 경우 초기화를 복제하거나 생성자를 공통 생성자로 리디렉션해야 합니다.
this
유효해 지기 전에 초기화가 발생하기 때문에 의존할 수 없습니다this
(즉, 다른 인스턴스 멤버에 의존할 수 없음).- 바깥쪽 클래스의 멤버만 초기화할 수 있습니다. 이니셜라이저 목록은 기본 클래스 생성자를 호출하기 전에 실행되기 때문에 기본 클래스 멤버를 설정할 수 없습니다.
생성자 본체
class Example3 {
T x;
Example3() {
x = value;
}
}
이점:
- 구성 인수를 활용할 수 있습니다.
- 단일 표현식을 통해 멤버를 초기화할 수 없는 경우와 같이 더 복잡한 초기화를 수행하는 데 사용할 수 있습니다.
- 사용할 수 있습니다
this
(즉, 다른 인스턴스 구성원을 사용할 수 있음). - 기본 클래스 멤버를 설정하는 데 사용할 수 있습니다.
단점:
late
final
null을 허용하지 않거나 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
}
반응형
'expert' 카테고리의 다른 글
Firestore - 예기치 않은 읽기 (0) | 2023.01.28 |
---|---|
Flutter에서 API를 사용하여 중첩된 json 데이터를 호출하는 방법은 무엇입니까? (0) | 2023.01.28 |
Apple Silicon(M1)에서 CocoaPods를 실행하는 방법 (0) | 2023.01.24 |
재사용 가능한 위젯을 생성하기 위한 함수와 클래스의 차이점은 무엇입니까? (0) | 2023.01.24 |
Flutter(Dart)의 객체 목록을 속성 값으로 정렬 (0) | 2023.01.24 |
댓글