먼저 dart에서 모든 타입의 기본값은 null이다.
기본값은 초기화를 따로 하지 않아도 대입되어 있는 값을 의미한다.
숫자 타입이여도 기본값이 null인데 그 이유로는 다트의 모든 타입은 object이기 때문에 null이 기본값으로 초기화된다. (물론 null-safety가 활성화되어있다면 타입에 ?를 붙여야 에러 없이 null로 초기화)
Number
위에서 먼저 말했던대로 숫자 타입도 기본적으로 Object로부터 파생된다.
그 다음에 특이하게 바로 int와 double이 아닌 num이란 타입이 있다.
이는 int와 double 모두 될 수 있는 숫자형 타입이다.
이미지 출처 : https://dart.dev/guides/language/numbers
num
일반적인 산술연산자와 절댓값을 구해주는 abs(), 올림해주는 ceil(), 내림해주는 floor() 등등의 함수를 가지고 있다. (만약 이외의 숫자형과 관련된 찾고자 하는게 있으면 dart:math 라이브러리에서 찾아보라고 한다.)
정수와 실수 모두 가질 수 있다.
int
값의 크기는 64비트 이하로 플랫폼에 의존하여 정해진다.
플랫폼에 의존한다는 말은 기본인 64비트 모바일 또는 데스크탑 프로세서에서 돌아가냐, 자바스크립트 엔진(웹)에서 돌아가냐의 차이를 말한다.
예시로 알 수 있는 것은 int의 최댓값인 2^63 - 1 (9223372036854775807)를 int 변수에 대입해서 컴파일하면 문제없이 수행된다.
하지만 js로 컴파일하면 'The integer literal 9223372036854775807 can't be represented exactly in JavaScript.' 란 에러가 발생한다.
js에서의 (안전한) 정수의 최댓값은 2^53 - 1 (9007199254740991) 이기 때문이다. (js에선 숫자형이 기본적으로 배정밀도)
이를 대입해서 다시 컴파일해보면 정상적으로 수행된다.
이 외에도 여러 상황에 따른 차이가 있지만 난 현재 웹을 사용하지 않아 js로 컴파일해서 쓰는 상황이 없으므로 다루지 않을 것이다.
double
값의 크기는 일반적인 부동소수점을 표현하는 방식의 표준인 IEEE754를 따른 배정밀도(64bit)의 크기를 가진다.
num number1 = 1;
num number2 = 1.123;
num number3 = number2.ceil();
int integer = 9223372036854775807; // js 이외 플랫폼에서의 정수 최댓값
// int integer = 9007199254740991; // js에서의 안전한 정수의 최댓값(js에선 부동소수점과 같이 사용하기 때문)
double floatingNumber = 1.12345678901234567890;
print(number1);
print(number2);
print(number3);
print(integer);
print(floatingNumber);
// output
// 1
// 1.123
// 2
// 9223372036854775807 (js에선 'The integer literal 9223372036854775807 can't be represented exactly in JavaScript.' 에러 발생)
// 1.1234567890123457
String
dart의 문자열 인코딩은 UTF-16이다. (UTF-16은 간단히 말하자면 문자 하나당 최소 16비트의 크기를 가지는 유니코드 변환 형식이다.)
왜 UTF-16인지에 대해선 정확히 알아보지 못했지만 크로스 플랫폼 호환을 위해서로 보인다.
String s1 = 'string';
String s2 = "string";
String s3 = '''multiline
string''';
String s4 = """multiline
string""";
String s5 = 'string ' "concatenate";
String s6 = 'string ' + 'concatenate';
String s7 = 'print number1 : $number1';
String s8 = 'print member : ${number1.abs()}';
String s9 = r'print raw string \\ $number1';
print(s1);
print(s2);
print(s3);
print(s4);
print(s5);
print(s6);
print(s7);
print(s8);
print(s9);
// output
// string
// string
/*
multiline
string
*/
/*
multiline
string
*/
// string concatenate
// string concatenate
// print number1 : 1
// print number's method : 1
// print raw string \\ $number1
Boolean
오직 true, false 두 컴파일 타임 상수만이 존재한다.
dart에서 조건문, assert문 내에 무조건 bool타입만 올 수 있다.
bool trueBool = true;
bool falseBool = false;
if (trueBool) {
print(trueBool);
}
if (falseBool) {
print(falseBool);
}
// if (0) {
// print('error');
// }
// Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
// output
// true
List(Array)
일반적으로 사용하는 list 자료형이다.
가변 길이인 list이지만 고정 길이인 array처럼 될 수 있다. (실제로 Array라는 object가 있는게 아닌 길이가 고정인 List일 뿐)
List의 filled, empty, from, generate 메서드의 named 매개변수인 growable을 false로 주면 고정 길이로 사용된다.
spread operator라는 다른 list의 요소들을 특정 list의 요소로 넣을 수 있는 연산자가 있다. (자세한건 이전에 작성한 글에 있다.)
var lists = [1, 2, 3, 'oh?', [1.1, 'good', {'map': 'val'}],];
var numberList = [1, 2, 3,];
List<Object>? nullList;
var inputWithSpreadOp = [...numberList, 4, 5, ...lists, ...?nullList];
var inputWithCondition = [if (trueBool) true, if (!falseBool) false];
List<int> fixedLengthList = List<int>.filled(5, -1, growable: false);
// fixedLengthList.add(5); // Unsupported operation: Cannot add to a fixed-length list 에러 발생, growable을 true로 하면 에러 발생하지 않음
print(lists);
print(lists[4]);
print(lists.runtimeType);
print(numberList);
print(numberList.runtimeType);
print(inputWithSpreadOp);
print(inputWithSpreadOp.runtimeType);
print(inputWithCondition);
print(inputWithCondition.runtimeType);
print(fixedLengthList);
print(fixedLengthList.runtimeType);
// output
// [1, 2, 3, oh?, [1.1, good, {map: val}]]
// [1.1, good, {map: val}]
// List<Object>
// [1, 2, 3]
// List<int>
// [1, 2, 3, 4, 5, 1, 2, 3, oh?, [1.1, good, {map: val}]]
// List<Object>
// [true, false]
// List<bool>
// [-1, -1, -1, -1, -1]
// List<int>
Set
중복된 값을 가지지 않는 자료형이다.
set은 {}로 선언한다. (선언할 때 아래 작성될 map자료형과 동일하게 {} 를 이용하지만 item이 단일로 있으면 set자료형이다.)
var justSet = {1, 2, '3', 4.0};
var spreadOp = {...justSet, 5};
Set<int> intSet = {1, 2, 3,};
intSet.add(10);
intSet.add(1); // 중복 안됨
print(justSet);
print(justSet.runtimeType);
print(spreadOp);
print(spreadOp.runtimeType);
print(intSet);
print(intSet.runtimeType);
// output
// {1, 2, 3, 4.0}
// _CompactLinkedHashSet<Object>
// {1, 2, 3, 4.0, 5}
// _CompactLinkedHashSet<Object>
// {1, 2, 3, 10}
// _CompactLinkedHashSet<int>
Map
key와 value로 이뤄진 자료형이다.
set과 같이 선언할 때 {} 를 사용하지만 key 와 value가 : 을 기준으로 나뉘어 item으로 있으면 map자료형이다.
var associate = {'key': 'value'};
var likeJson = {'key1': 'value1', 'key2': 2, 'key3': [1, 2, 3,], 'key4': {1: 'sub'},};
print(associate);
print(associate.runtimeType);
print(likeJson);
print(likeJson.runtimeType);
print((likeJson['key4'] as Map<int, Object>)[1]);
// output
// {key: value}
// _InternalLinkedHashMap<String, String>
// {key1: value1, key2: 2, key3: [1, 2, 3], key4: {subObj: sub}}
// _InternalLinkedHashMap<String, Object>
// sub
전체 코드
참고
'개발 > Dart' 카테고리의 다른 글
Object dynamic var 차이 (0) | 2022.08.02 |
---|---|
dot(.) 개수에 따른 의미 (2개와 3개) (0) | 2022.06.07 |
factory 키워드 (싱글턴 패턴) (0) | 2022.05.26 |