변수
A tour of the Dart language 페이지를 공부하면서 정리한 내용입니다.
변수는 아래와 같이 선언하고 초기화 합니다.
var name = 'Bob';변수에는 객체의 참조를 저장합니다. 변수 name은 "Bob"을 값으로 갖는 String 객체를 참조합니다. 컴파일러에 의해 name은 String 타입으로 추론됩니다. 변수가 특정 타입으로 제한되지 않을 경우 Object 또는 dynamic을 사용할 수 있습니다.
Object name = 'Bob';
dynamic name = 'Bob';변수 선언 시 명시적으로 타입을 지정할 수도 있습니다.
String name = 'Bob';기본값
Nullable 타입의 기본값(Default value)은 null입니다. 숫자를 포함 Dart의 모든 것은 객체이므로 nullable 정수 타입도 초기값은 null을 갖습니다.
int? lineCount;
assert(lineCount == null);Null safety를 사용할 때 non-nullable 변수는 반드시 초기화 후에 사용해야 합니다.
int lineCount = 0;지역 변수는 선언 지점에 초기화할 필요는 없지만, 반드시 초기화 후에 사용해야 합니다. 예를 들어, 아래 예제에서 컴파일러는 lineCount가 print() 함수에 전달될 때 반드시 초기화된다는 사실을 알 수 있어서 정상적으로 컴파일 및 실행이 됩니다.
import 'dart:convert';
import 'dart:math';
String poemFlower = """꽃 - 김춘수
내가 그의 이름을 불러주기 전에는
그는 다만
하나의 몸짓에 지나지 않았다.
내가 그의 이름을 불러주었을 때,
그는 나에게로 와서
꽃이 되었다.
내가 그의 이름을 불러준 것처럼
나의 이 빛깔과 향기에 알맞은
누가 나의 이름을 불러다오.
그에게로 가서 나도
그의 꽃이 되고 싶다.
우리들은 모두
무엇이 되고 싶다.
너는 나에게 나는 너에게
잊혀지지 않는 하나의 눈짓이 되고 싶다.
""";
void main() {
int lineCount;
// Error: Non-nullable variable 'lineCount' must be assigned before it can be used.
// print(lineCount);
bool weLikeToCount = nextBoolean();
if (weLikeToCount) {
lineCount = countLines(poemFlower);
} else {
lineCount = 0;
}
// 컴파일러는 변수가 초기화 될 것을 알기 때문에 정상적으로 컴파일 됩니다.
print(lineCount);
}
bool nextBoolean() {
return Random().nextBool();
}
int countLines(String text) {
return LineSplitter().convert(text).length;
}최상위 변수와 클래스 변수는 게으른 초기화(Lazily initialized)를 합니다. 해당 변수들은 최초로 사용되는 시점에 초기화 됩니다.
late 변수
Dart 2.12 버전에서 late 제어자(Modifier)가 추가되었으며, 아래 두 가지 경우에 사용합니다.
Non-nullable 변수를 선언만 하고 초기화하지 않는 경우
변수가 게으른 초기화를 하는 경우
Dart 컴파일러의 제어 흐름 분석은 non-nullable 변수가 사용되기 전에 null이 아님을 알 수 있습니다. 하지만 최상위 변수와 인스턴스 변수의 경우 분석이 실패할 수 있습니다. 위 예제에서도 lineCount가 초기화되기 전에 print()에 전달했는데, 이 경우 컴파일 에러가 발생합니다.
변수가 사용되기 전에 반드시 초기화 된다는 사실을 알고 있다면, late 제어자를 이용해 Dart 컴파일러에게 사실을 알릴 수 있습니다.
late 제어자를 이용해 변수를 선언하면서 동시에 초기화하면 변수를 처음 사용하는 시점에 게으른 초기화를 수행합니다. 게으른 초기화는 몇 가지 경우 유용하게 사용할 수 있습니다.
변수가 실제로 사용되지 않을 수 있는 경우
변수 초기화 비용이 비싼 경우
인스턴스 변수의 초기화를 진행 중인 상태에서 해당 인스턴스의 초기화 프로그램이
this에 접근이 필요한 경우
아래 예제에서 temperature 변수는 사용되지 않기 때문에 변수 초기화를 위해서 값비싼 _readThermometer() 함수는 호출되지 않습니다.
final과 const
변수를 변경하고 싶지 않다면 var 대신 final 또는 const를 사용해주세요. final변수는 한번만 할당할 수 있도록 합니다. const 변수는 컴파일 타임 상수(Compile-time constant)입니다. const 변수는 값을 변경할 수 없고, 암묵적으로 final이기 때문에 재할당하는 것도 불가능합니다.
final 변수는 아래와 같이 선언하고 초기화 합니다. final 변수를 재할당 하려고 시도하면 컴파일 에러가 발생합니다. final 변수는 재할당할 수 없지만, 객체의 속성을 변경할 수는 있습니다.
컴일 타임 상수로 만들고 싶다면 const를 사용합니다. const 변수가 클래스 수준에 존재한다면, static const로 표현합니다. 숫자나 문자열 리터럴, 상수간의 연산 결과 등은 컴파일 타임 상수로 설정할 수 있습니다. const 변수는 객체의 속성도 변경할 수 없습니다.
const 키워드는 상수 변수를 선언하는 것 외에 상수 값을 생성하거나, 상수 값을 생성하는 생성자를 선언할 수도 있습니다. 클래스 인스턴스 생성 시 const로 선언하면 해당 객체는 컴파일러에 의해서 최적화 됩니다. 컴파일러는 객체를 불변(Immutable)하게 만들고, 동일한 객체 생성에 대해서 같은 메모리를 가르키게 합니다.
타입 검사(Type checks), 타입 케스트(Type Casts), 컬렉션 if, 전개 연산자(Spread operators) ..., ...?를 사용해 상수를 정의할 수 있습니다.
Last updated