Record
void main() {
final res = nameAndAge({
"name": "다미",
"age": 26,
});
print(res);
print(res.$1);
print(res.$2);
}
//Record
(String, int) nameAndAge(Map<String, dynamic> json) {
return (json["name"] as String, json["age"] as int);
}
(다미, 26)
다미
26
name은 String, age는 int 타입으로 들어갈 거라고 미리 설계
List에서는 res[0] 이런 식으로 받아야 했지만
Tuple에서는 res.$1 이렇게 받으면 됨
void main() {
final resPet = getPetWithType();
for (final item in resPet) {
print(item.$1);
print(item.$2);
}
final resPet2 = getPetWithType2();
for (final item in resPet2) {
print(item.name);
print(item.age);
}
}
List<Map<String, dynamic>> getPet() {
return [
{"name": "chacha", "age": 6},
{"name": "mongchi", "age": 2},
];
}
List<(String, int)> getPetWithType() {
return [
("chacha", 6),
("mongchi", 2),
];
}
List<({String name, int age})> getPetWithType2() {
return [
(name: "chacha", age: 6),
(name: "mongchi", age: 2),
];
}
chacha
6
mongchi
2
chacha
6
mongchi
2
-> Record 형태 사용하면 type과 type의 순서를 무조건 보장받을 수 있음
변수 개수는 무한히 할 수 있음
destructuring
void main() {
final (name, age) = ("dami", 26);
print(name);
print(age);
final pets = ['chacha', 'mongchi'];
final [String a, String b] = pets; //데이터타입 맞춰춰야 에러 안남
print(a);
print(b);
final nums = [1, 2, 3, 4, 5, 6];
final [x, y, ..., z] = nums;
print(x);
print(y);
print(z);
}
dami
26
chacha
mongchi
1
2
6
..., 이용해 중간 원소들을 건너뛸 수 있는데 한 리스트 안에 하나만 쓸 수 있음
void main() {
final nums = [1, 2, 3, 4, 5, 6];
final [xx, yy, ...rest, zz] = nums;
print(rest);
}
[3, 4, 5]
...rest 하고 rest 출력하면 리스트에서 건너뛴 값들이 출력됨
final [_, y, ...rest2, _] = nums;
이처럼 _ 이용해 값들을 무시할 수도 있음
void main() {
final damiMap = {"name": "dami", "age": 26};
final {"name": damiName, "age": damiAge} = damiMap;
print(damiName);
print(damiAge);
}
dami
26
final {"name": damiName, "age": damiAge} = damiMap;
위 부분은 name과 age의 key를 저렇게 이름붙인다는 것
void main() {
final damiIdol = Idol(name: "dami", age: 26);
final Idol(name: damiName, age: damiAge) = damiIdol;
print(damiName);
print(damiAge);
}
class Idol{
final String name;
final int age;
Idol({
required this.name,
required this.age,
});
}
타입을 정확히 맞춰주면 변수 두 번 선언할 필요없이 선언문에서 destructuring해서 이름 정해줄 수 있음
거의 대부분의 데이터 구조에서 사용 가능
pattern matching
switcher
void main() {
//validation
final dami = ("dami", 26);
final (name as String, age as int) = dami;
print(name);
print(age);
switcher("aaa");
switcher("bbb");
switcher(['1', '2']);
switcher([1, 2]);
switcher([1, 2, 3]);
switcher([4, 5, 6]);
switcher([4, 5, 6, 7]);
switcher([6, 9]);
switcher([6, '9']);
switcher(7);
}
void switcher(dynamic anything){
switch(anything){
case "aaa":
print("match: aaa");
case ['1', '2']:
print("match: [1, 2]");
case [_, _, _]:
print("match: [_, _, _]");
case [int a, int b]:
print("match: [int $a, $b]");
case < 10 && >5: //switcher(7);을 위한 것
print("match: <10 && >5");
default:
print("no match");
}
}
void main() {
print(switcher(5, true));
print(switcher(7, true));
print(switcher(7, false));
}
String switcher(dynamic val, bool condition) => switch (val) {
5 => "match: 5",
7 when condition => "match 7 and true",
_ => "no match",
};
match: 5
match 7 and true
no match
바로 반환할 수 있도록 case문을 쓸 수도 있음
void main() {
forLooper();
}
void forLooper(){
final List<Map<String, dynamic>> pets = [
{"name": "chacha", "age": 6,},
{"name": "mongchi", "age": 2,},
];
for(final pet in pets){
print(pet["name"]);
print(pet["age"]);
}
for(var {"name": name, "age": age} in pets){
print(name);
print(age);
}
}
chacha
6
mongchi
2
void main() {
ifMatcher();
}
void ifMatcher(){
final cat = {"name": "chacha", "age": 6};
if(cat case {"name": String name, "age": int age}){
print(name);
print(age);
}
}
chacha
6
if문에서 지정한 패턴이 충족되어야 진행됨
final class Person{
final String name;
final int age;
Person({
required this.name,
required this.age,
});
final로 class 선언하면 extends, implement, 또는 mixin으로 사용 불가
base class Person{
final String name;
final int age;
Person({
required this.name,
required this.age,
});
base로 선언하면 extend는 가능하지만 implement는 불가
base, sealed, final로 선언된 클래스만 extend가 가능
interface class Person{
final String name;
final int age;
Person({
required this.name,
required this.age,
});
interface로 선언하면 implement만 가능(extend는 불가)
sealed class Person {}
class Idol extends Person {}
class Engineer extends Person {}
class Chef extends Person {}
String whoIsHe(Person person) => switch (person) {
Idol i => "아이돌",
Engineer e => "엔지니어",
Chef c => "셰프",
_ => "나머지",
};
sealed 클래스는 abstract이면서 final
그리고 pattern matching을 사용할 수 있도록 해 줌
클래스 선언한 것들을 다 써줘야 에러 안뜸
- => "나머지" 이런 식으로라도!
mixin class
mixin class DogMixin{
String bark(){
return "멍멍";
}
}
class Dog with DogMixin{}
mixin은 extends나 with 사용 불가
-> mixin class도 마찬가지로 사용 불가
class는 on 키워드 사용 불가
-> mixin class도 마찬가지로 사용 불가
'CS > Flutter | Dart' 카테고리의 다른 글
Widget Tree, MainAxisAlignment, CrossAxisAlignment (0) | 2023.07.17 |
---|---|
Flutter Hello World,,,! (0) | 2023.07.16 |
Dart Asynchronous Programming - Stream, yield (0) | 2023.07.12 |
Dart Asynchronous Programming - Future (1) | 2023.07.12 |
Dart cascading operator, functional programming (0) | 2023.07.12 |