다트 문법 정리 (1) 변수
본 글은 내가 보려고 정리한 글이다. 다트를 처음 배우는데, 플러터 개발할 때마다 다트 문법 찾아보기 힘들어서 여기에 한 번에 정리하려 한다.
다트를 가장 쉽게 설명하는 튜토리얼, 그리고 이펙티브 다트 문서까지 제공하는 곳이 바로 다트 공식 문서이다. 이 중 Dart Tour의 내용을 요약하는 중이다.
그 첫 번째가 다트의 변수 관련 문법이다. 다트는 타입 언어이며, 변수마다 타입을 지정해줘야 한다. 또한 기본적으로 null safety가 적용되어 있어서, null을 사용하려면 타입 키워드 뒤에 ?을 붙여주어야 한다. 또한 C++의 템플릿과 마찬가지로 다트에선 제네릭을 제공한다.
또한 다트에서는 C++의 auto
와 마찬가지로 타입 추론을 지원한다. 그게 바로 var
인데, var
변수는 기본적으로 컴파일러가 알아서 타입을 추론해준다.
다트 기본 변수 타입
- num
int
와 double
형 변수를 모두 나타낸다.
num number1 = 10;
num number2 = 10.0;
- int
integer 32비트 정수형이다.
int number = 10
- double
double 64비트 실수형이다.
double number = 10.0;
- String
문자열을 나타낸다. C++의 std::string
과 같은 역할이다. 다트에선 String
, List
등과 같은 컨테이너는 앞 글자가 대문자임에 주의하자.
String str1 = "Hello world";
- bool
참(true
)와 거짓(false
)를 나타내는 논리값이다.
bool flag0 = true;
bool flag1 = false;
- dynamic
어떤 타입이든 받을 수 있다. C++의 std::any
와 비슷하다. 또는 파이썬, 자바스크립트와 같은 타입리스 형 언어들과 비슷한 역할이다.위 예시에서 dynamic
으로 선언된 a에 대해 어떠한 타입을 대입하는 것도 허용된다. 개인적으로 C++의 문법에 익숙한 나로썬 사용하기 꺼려지는 문법이다.
dynamic a = 1;
a = 'hello';
a = 1.1; a = true;
- List
리스트이다. C++의 std::list
처럼 더블 링크드 리스트의 그 리스트는 아니고, std::vector
와 같이 배열 형태로 구현되어 있다.마찬가지로 앞글자가 대문자임에 주의하자. 한편 다트에서 위와 같이 제네릭을 사용하지 않고 다음과 같이 선언 및 정의할 수도 있다.list1
을 보면 var로 선언한 것을 알 수 있다. 이때 list1
, list2
의 타입은 List<int>
형이다.
한편 list2
를 보면, ...
이란 연산자를 사용한 것을 볼 수 있는데, 이는 Spread Operator라 하며, 한 리스트 안에 또다른 리스트를 삽입할 때 사용할 수 있다.List
에는 length
등의 편리한 메소드 함수들을 추가 제공한다.
var list1 = [1, 2, 3];
var list2 = [0, ...list1];
print(list2); // [0, 1, 2, 3]
List<String> list_str = ['a', 'b', 'c'];
List<int> list_int = [1, 2, 3]; List<num> list_num = [1, 2, 3, 3.14];
List<dynamic> list_dynamic = [1, 2, 3.14, 'a', 'b', true];
- Map
C++의 std::unordered_map
과 같다. 따라서 key들이 정렬되지 않음을 주의하자. 대신 해시맵과 마찬가지로 O(1)의 시간 안에 삽입 삭제가 이루어진다.
var gifts = { // Key: Value 'first': 'partridge', 'second': 'turtledoves', 'fifth': 'golden rings' };
var nobleGases = {
2: 'helium',
10: 'neon',
18: 'argon',
};
위 코드에서 gifts
의 타입은 Map<String, String>
이고, nobleGases
의 타입은 Map<int, String>
이다.
또는 다음과 같이 Map constructor를 이용하기도 한다.
var gifts = Map<String, String>();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';
var nobleGases = Map<int, String>();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';
- Set
집합이다. C++의 std::unordered_set
과 같다.
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
Set<int> numbers = { 1, 3, 5, 7 };
halogens의 타입은 Set<String>
이다.
다음과 같이 Set constructor를 이용할 수도 있다.
var names = <String>{};
// Set<String> names = {}; // This works, too.
// var names = {}; // Creates a map, not a set.
Set
에는 {}, Map
에는 [] 이 사용됨을 기억하자.
다트 변수 키워드
const, final
const
는 컴파일 상수로, C++의 constexpr
의 역할이다.final
은 상수화로, C++의 const
와 같다.
const
, final
은 사용할 수 있는 곳에 모두 사용하는 것이 좋다.
Late variables
다트는 기본적으로 null safe 언어이기 때문에, 처음 변수를 선언하면 무조건 초기화를 해주어야 한다. 하지만 초기화가 선언 이후에 돼야 하는 경우, 우리는 late
키워드를 붙여서 이것이 후에 값을 가질 것이다라고 컴파일러에게 알려줄 수 있다.
late String description;
void main() {
description = 'Feijoada!';
print(description);
}
late
를 사용하는 시나리오는 두 가지 경우가 있다:
- 선언 이후에 초기화되는 non-nullable 한 변수를 만들 때
- 뒤늦게 초기화되는 변수
? 키워드
다트는 기본적으로 null safe한 언어이기에 그냥 변수를 선언하면 모두 non-nullable하다. 그러나 변수의 타입 뒤에 ?
을 붙여준다면 nullable한 변수를 만들 수 있다.
int? lineCount;
print(lineCount); // null
assert(lineCount == null);
lineCount
는 nullable한 변수로써 null값을 가질 수 있다.