널을 할당 가능하게 하려면 ? 기호를 추가하면 된다.
void main() {
int? a;
a = null;
print('a is $a.');
String? name;
name = null;
print('you name is $name');
}
----------------------------[result]
a is null.
you name is null
리스트를 사용하는 경우 '?' 위치
void main() {
List<String> aListOfStrings = ['one', 'two', 'three'];
// 리스트 멤버가 없는경우는 , 빈 리스트 할당으로 ? 대체 가능
List<String> aNullableListOfStrings = [];
// 리스트 멤버가 없는경우는 , 타입<> 뒤에 ? 위치
List<String>? aNullableListOfStrings1;
// 리스트 요소중에 널이 있으면 <> 안에 ? 위치
List<String?> aListOfNullableStrings = ['one', null, 'three'];
print('aListOfStrings is $aListOfStrings.');
print('aNullableListOfStrings is $aNullableListOfStrings.');
print('aNullableListOfStrings1 is $aNullableListOfStrings1.');
print('aListOfNullableStrings is $aListOfNullableStrings.');
}
------------------------------[result]
aListOfStrings is [one, two, three].
aNullableListOfStrings is [].
aNullableListOfStrings1 is null.
aListOfNullableStrings is [one, null, three].
The null assertion operator (!)
int? couldReturnNullButDoesnt() => -3;
void main() {
int? couldBeNullButIsnt = 1;
List<int?> listThatCouldHoldNulls = [2, null, 4];
int a = couldBeNullButIsnt;
// ! 위치 중요함, 문법의 구조에 따라서 ! 위치가 다름.
// 널이 아니라고 확신할때, ! 추가하면 됨. 리스트의 첫번째 요소는 널이 아님
int b = listThatCouldHoldNulls.first!; // first item in the list
// 함수의 리턴값은 널이 절대 아니므로 함수명 바로 뒤에 ! 추가
int c = couldReturnNullButDoesnt()!.abs(); // absolute value
print('a is $a.');
print('b is $b.');
print('c is $c.');
}
----------------------------------[result]
a is 1.
b is 2.
c is 3.
변수가 널일 경우, 로직을 추가해서 회피하는 코드
int getLength(String? str) {
// Add null check here
if (str == null) {
return 0;
}
else {
return str.length;
}
}
void main() {
print(getLength('This is a string!'));
}
-------------------------------[result]
17
Exception 처리
int getLength(String? str) {
// Try throwing an exception here if `str` is null.
if(str == null){
throw Exception();
}
return str.length;
}
void main() {
print(getLength(null));
}
-----------------------------------[result]
Uncaught Error: Exception
Late keyword
- Don’t assign that variable a value yet.
- You will assign it a value later.
- You’ll make sure that the variable has a value before the variable is used.
class Meal {
// 생성자가 없는 경우
late String _description;
void set description(String str) {
_description = str;
}
String get description => _description;
}
void main() {
final myMeal = Meal();
myMeal.description = 'Feijoada!';
print(myMeal.description);
}
------------------------------[result]
Feijoada!
Late circular references
The late keyword is helpful for tricky patterns like circular references. The following code has two objects that need to maintain non-nullable references to each other. Try using the late keyword to fix this code.
Note that you don’t need to remove final. You can create late final variables: you set their values once, and after that they’re read-only.
class Team {
late final Coach coach;
}
class Coach {
late final Team team;
}
void main() {
final myTeam = Team();
final myCoach = Coach();
myTeam.coach = myCoach;
myCoach.team = myTeam;
print('All done!');
}
------------------------------[result]
All done!
Late and lazy
Here’s another pattern that late can help with: lazy initialization for expensive non-nullable fields. Try this:
- Run this code without changing it, and note the output.
- Think: What will change if you make _cache a late field?
- Make _cache a late field, and run the code. Was your prediction correct?
int _computeValue() {
print('In _computeValue...');
return 3;
}
class CachedValueProvider {
// late 키워드가 없는 경우
final _cache = _computeValue();
int get value => _cache;
}
void main() {
print('Calling constructor...');
var provider = CachedValueProvider();
print('Getting value...');
print('The value is ${provider.value}!');
}
---------------------------[result]
Calling constructor...
In _computeValue...
Getting value...
The value is 3!
late 키워드가 있는 경우, 출력 순서가 변경된다.
int _computeValue() {
print('In _computeValue...');
return 3;
}
class CachedValueProvider {
// late 키워드가 있는 경우
late final _cache = _computeValue();
int get value => _cache;
}
void main() {
print('Calling constructor...');
var provider = CachedValueProvider();
print('Getting value...');
print('The value is ${provider.value}!');
}
---------------------------[result]
Calling constructor...
Getting value...
In _computeValue...
The value is 3!
'Dart' 카테고리의 다른 글
[Dart] Class - getter, setter (0) | 2021.05.27 |
---|---|
[Dart] Class - 선언 및 생성자 (0) | 2021.05.27 |
[Dart] Stream 처리. (0) | 2021.05.01 |
[Dart] Future, async-await (0) | 2021.04.30 |
[Dart] 상속과 변수 초기화 (0) | 2021.04.30 |