728x90

Class Fruits의 인스턴스를 생성하고 a.list 의 값을 확인해보자.

참조변수 b 에 a.list 를 할당하는 것은 shallow copy(얕은 복사)로 같은 메모리 주소를 바라보고 있어 동일한 값을 가진다.

참조변수 b에 새로운 값을 할당하고 나서 a.list 를 출력해보면 새로 추가한 수박이 반영되어 있는 걸 확인할 수 있다.

 

깊은 복사 방법은

- toList()를 추가하여 새로운 배열을 만드는 방법,

- 전개 연산자(...)를 사용하는 방법,

- map()함수를 활용하는 방법

이 있다.

class Fruits {
  List<String> _list = ['사과','복숭아','배','감','호두','자두'];
  List<String> get list => _list;
}
 
void main(){
  final a = Fruits();
  print(a.list); // [사과, 복숭아, 배, 감, 호두, 자두]
  List<String> b = a.list;
  print(b);      // [사과, 복숭아, 배, 감, 호두, 자두]
  print(a.list == b); // true 얕은 복사(동일한 메모리 주소를 가짐)
 
  b.add('수박');
  print(a.list); // [사과, 복숭아, 배, 감, 호두, 자두, 수박]
 
  List<String> c = a.list.toList(); // 새로운 배열
  print(c == a.list); // fasle 깊은 복사(deep copy)
  print(c); // [사과, 복숭아, 배, 감, 호두, 자두, 수박]
  /***
   * 깊은 복사란, 값이 동일한 객체를 새롭게 생성하는 것을 의미한다.
   */
 
  List<String> d = [...a.list]; // 전개 연산자를 활용하여 새로운 배열
  print(d == a.list); // false 깊은 복사
  print(d); // [사과, 복숭아, 배, 감, 호두, 자두, 수박]
 
  List<String> e = a.list.map((e) => e).toList();
  // map은 배열을 순환하며 값을 변경할 수 있는 함수이다.
  // map()은 Iterable을 반환한다.
  print('-------------------------------');
  print(e); // [사과, 복숭아, 배, 감, 호두, 자두, 수박]
  print(e == a.list); // false. 깊은 복사
 
  c.add('살구');
  print(c);      // [사과, 복숭아, 배, 감, 호두, 자두, 수박, 살구]
  print(a.list); // [사과, 복숭아, 배, 감, 호두, 자두, 수박]
 
  d.add('포도');
  a.list.remove('복숭아');
  print(d);      // [사과, 복숭아, 배, 감, 호두, 자두, 수박, 포도]
  print(a.list); // [사과, 배, 감, 호두, 자두, 수박]
 
}

 

 

그리고 copyWith를 활용하는 깊은 복사 방법을 알아보자.

class Person {
  final String name;
  final int age;
 
  Person({
    required this.name,
    required this.age,
  });
 
  Person copyWith({
    String? name,
    int? age,
  }) {
    return Person(
      name: name ?? this.name,
      age: age ?? this.age,
    );
  }
 
  @override
  String toString() {
    return 'Person{name: $name, age: $age}';
  }
}
 
void main(){
  final a = Person(name: '홍길동', age: 33);
  final b = Person(name: '홍길동', age: 33);
  print(a == b); // fasle. 객체 생성할 때마다 메모리 주소가 새로 할당된다.
 
  final d = a;
  print(d == a); // true 얕은 복사(동일한 메모리 주소를 가짐)
 
  final e = a.copyWith(); // 깊은 복사
  print(a.toString()); // Person{name: 홍길동, age: 33}
  print(e.toString()); // Person{name: 홍길동, age: 33}
  print(e == a); // false. 서로 다른 메모리 주소
 
}
 

 

 

 

 

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

Dart 값 비교 - Equatable 패키지  (0) 2024.01.17
Dart cascade notation  (0) 2024.01.16
Dart List.where  (0) 2024.01.16
[Dart 고급] Dart asMap, entries  (0) 2024.01.16
Dart fold 함수  (2) 2023.12.15
블로그 이미지

Link2Me

,
728x90

Operator ==

oop라는 명칭이 생겨난 이유는 모든 클래스가 기본적으로 object를 extend 하기 때문이다.
Object라는 최상위 클래스가 제공해주는 모든 파라미터들을 모든 클래스들이 사용할 수 있다는 의미다.
대부분의 언어에서는 이 Object라는 클래스에 A 인스턴스와 B 인스턴스를 비교하는 알고리즘이 정의되어 있다.
Dart 에서는 operator라는 함수에 정의 되어있고, 이를 override 함으로써 값 비교 알고리즘을 자유롭게 변경할 수 있다.


Hash Code

hashcode 함수는 Map 또는 Set에서 키의 역할을 하게 된다.
Map이나 Set은 키가 중복으로 저장될 수 없기 떄문에 Set, Map의 키로 Object가 저장되었을 때 어떻게 키값을 정의할지가 중요하다.

프로퍼티(변수)가 늘어나면 늘어날수록 operator와 hashcode를 작성하는것이 귀찮아진다.
dart에서는 equatable클래스를 상속받아 이 문제를 해결하고 있다.

Equatable 클래스를 상속받고 props 라는 메소드를 override 해주면 된다.

 

import 'package:equatable/equatable.dart';
 
class A extends Equatable {
  // Equatable 패키지는 불변 객체를 전제로 설계되었다.
  final int a;
  final int b;
 
  const A({
    required this.a,
    required this.b,
  });
 
  @override
  List<Object?> get props => [this.a, this.b];
  // Equatable 클래스를 상속을 받고
  // props 라는 메소드를 override 해주면 된다.
  // props는 비교시 사용하고 싶은 속성을 배열로 반환해주면 된다.
}
 
void main() {
  final a1 = A(a:88, b:53);
  final a2 = A(a:88, b:53);
 
  print(a1 == a2); // true
  print(a1); // A(88,53)
}
 
/***
 * Dart 기본적으로 참조 비교(Reference Equality)를 사용하기 때문에,
 * 가변 객체인 A 인스턴스는 생성할 때 마다 다른 메모리에 할당되어 false를 반환
 * Equatable 패키지를 이용하면 보다 손쉽게 값 비교를 구현할 수 있다.
 */

 

equatable 패키지 설치는 https://pub.dev/packages/equatable 를 참조하면 된다.

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

Dart 얕은 복사(shallow copy), 깊은 복사(deep copy)  (0) 2024.01.17
Dart cascade notation  (0) 2024.01.16
Dart List.where  (0) 2024.01.16
[Dart 고급] Dart asMap, entries  (0) 2024.01.16
Dart fold 함수  (2) 2023.12.15
블로그 이미지

Link2Me

,
728x90

Dart 에 cascade notation(.., ?..) 이 있다.

처음 접하다보니 이게 뭔가 싶어서 찾아보고 적어둔다.

 

아래 예제의 출처는 https://www.educative.io/answers/what-is-dart-cascade-notation  인데, 약간 주석 내용을 포함해서 조금 더 보완했다.

 

class Example{
  var a;
  var b;
 
  void bSetter(b) {
    this.b = b;
  }
 
  void printValues(){
    print(this.a);
    print(this.b);
  }
}
 
void main() {
  //Instantiating two Example objects
  Example eg1 = new Example(); // 변수는 참조(메모리주소)를 저장한다.
  Example eg2 = new Example();
 
  //Using the .. operator for operations on Example object
  print("Example 1 results:");
  eg1
    ..a = 88
    ..bSetter(53)
    ..printValues();
 
  //The same operations as above but without the .. operator
  print("Example 2 results:");
  eg2.a = 88;
  eg2.bSetter(53);
  eg2.printValues();
 
  // 위 2개는 출력된 결과는 동일하다.
 
  print(eg1 == eg2); // false (메모리 주소 비교했는데 메모리 주소가 다르다.)
  /***
   * 배열은 가변 객체(Mutable Object), Custom Class 도 가변 객체
   * 객체 생성시, 가변 객체는 항상 새로운 메모리를 할당하고,
   * 불변 객체(Immutable Object)는 값이 동일하다면 기존에 생성한 객체를 재활용한다.
   * 불변 객체로 String, int, double, bool, const로 선언된 객체 등이 있다.
   * const는 컴파일 타임에 고정 값인 객체 앞에만 선언할 수 있다.
   * 컴파일 타임 : 앱 실행 전 소스코드를 기계어로 변환하는 시점
   */
}

 

cascade notation(.., ?..) 을 사용하면 같은 객체에 대해 일련의 작업을 수행할 수 있다. 

인스턴스 멤버에 접근하는 것 외에도 같은 객체에서 인스턴스 메서드를 호출할 수도 있다. 

이렇게 하면 임시 변수를 만드는 단계가 줄어들고 더 유동적인 코드를 작성할 수 있다.

 

 
  final fruits = Fruits();
 
  fruits.insert('사과');
  fruits.insert('수박');
  fruits.insert('오이');
  fruits.insert('참외');
  fruits.insert('딸기');
  fruits.insert('배');
  fruits.insert('감');
 
  // 아래와 같이 캐스케이드 연산자를 사용해서 값을 추가할 수도 있다.
  Fruits()
    ..insert('사과')
    ..insert('수박')
    ..insert('오이')
    ..insert('참외')
    ..insert('딸기')
    ..insert('배')
    ..insert('감');

 

하지만 위의 예시는 잘못된 결과가 반환된다.

왜? Custom Class 객체를 생성할 때마다 메모리 주소가 다르기 때문이다.

 

  fruits
    ..insert('사과')
    ..insert('수박')
    ..insert('오이')
    ..insert('참외')
    ..insert('딸기')
    ..insert('배')
    ..insert('감');

 

위와 같이 해야 정상적인 결과를 반환한다.

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

Dart 얕은 복사(shallow copy), 깊은 복사(deep copy)  (0) 2024.01.17
Dart 값 비교 - Equatable 패키지  (0) 2024.01.17
Dart List.where  (0) 2024.01.16
[Dart 고급] Dart asMap, entries  (0) 2024.01.16
Dart fold 함수  (2) 2023.12.15
블로그 이미지

Link2Me

,
728x90

Flutter 코드 구현시 자주 사용하는 기능이라 적어둔다.

void main1(){
  var myList = [0842697];
  var result = myList.where((item) => item > 5).toList();
  print(result); // [6, 8, 7]
  var fst = myList.firstWhere((item) => item > 5);
  print(fst); // 8
  var last = myList.lastWhere((item) => item > 5);
  print(last); // 7
}
 
void main(){
  List<String> names = ['Max''John''Sara''Peter''Charlie'];
  Iterable<String> v_name = names.where((element) => element.contains('a'));
  print(v_name); // (Max, Sara, Charlie)
}

 

 

 

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

Dart 값 비교 - Equatable 패키지  (0) 2024.01.17
Dart cascade notation  (0) 2024.01.16
[Dart 고급] Dart asMap, entries  (0) 2024.01.16
Dart fold 함수  (2) 2023.12.15
Dart mixin  (0) 2023.12.11
블로그 이미지

Link2Me

,
728x90

Class Model 생성할 때 key 가 되는 id 가 없이 구현될 경우를 살펴보고자 한다.

값을 수정하거나, 삭제할 때 index 로 삭제해야 한다.

Model 에는 index 가 없기 때문에 asMap 으로 변환하여 index 기준으로 수정, 삭제할 수 있다.

 

Custom Model 대신에 간단한 테스트를 위해 String 으로 대체했다.

Riverpod 용 Provider 로 구현 시에는 _list 대신에 state 로 변경하면 된다.

 

asMap()을 사용하면 Map으로 형변환이 가능하다.

Map 에서 .keys를 사용하면 key 값을, .values를 사용하면 value 값을 가져온다.

map.keys 는 Iterable 객체로 반환되기 때문에 .toList()를 사용해서 변형해줘야 List 객체가 된다.

asMap().entries.map 을 사용하면 새로운 리스트가 만들어진다. entry 조건을 비교하여 값을 update할 수 있다.

class Fruits {
  List<String> _list = const [];
 
  List<String> get list => _list;
 
  void insert(String newItem) {
    _list = [..._list, newItem];
  }
 
  void update(int selectedIndex, String newItem) {
    _list = _list
        .asMap()
        .entries
        .map((entry) => selectedIndex == entry.key ? newItem : entry.value)
        .toList();
  }
 
  void delete(List<String> deleteList) {
    _list = _list.where((item) => !deleteList.contains(item)).toList();
  }
 
  void deleteIndex(int index) {
    _list = List.from(_list)..removeAt(index);
  }
}
 
void main() {
  final fruits = Fruits();
 
  fruits.insert('사과');
  fruits.insert('수박');
  fruits.insert('오이');
  fruits.insert('참외');
  fruits.insert('딸기');
  fruits.insert('배');
  fruits.insert('감');
 
  print(fruits.list); // [사과, 수박, 오이, 참외, 딸기, 배, 감]
  final map = fruits.list.asMap();
  print(map); // {0: 사과, 1: 수박, 2: 오이, 3: 참외, 4: 딸기, 5: 배, 6: 감}
 
  final map_keys = map.keys.toList(); // List 객체
  print(map_keys); // [0, 1, 2, 3, 4, 5, 6]
  print(map.keys); // Iterable 객체 - (0, 1, 2, 3, 4, 5, 6)
  print(map.values); // Iterable 객체 - (사과, 수박, 오이, 참외, 딸기, 배, 감)
 
  print(map.keys is Iterable); // true
  print(map.keys.toList() is List); // true
 
  int selectedIndex = 2;
  fruits.update(selectedIndex, '포도');
  print(fruits.list); // [사과, 수박, 포도, 참외, 딸기, 배, 감]
 
  List<String> deleteList = ['참외''배'];
  fruits.delete(deleteList);
  print(fruits.list); // [사과, 수박, 포도, 딸기, 감]
 
  fruits.deleteIndex(2);
  print(fruits.list); // [사과, 수박, 딸기, 감]
 
  fruits.insert('자두');
  fruits.insert('살구');
  fruits.insert('복숭아');
  print(fruits.list); // [사과, 수박, 딸기, 감, 자두, 살구, 복숭아]
}
 

 

 

 

 

 

 

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

Dart cascade notation  (0) 2024.01.16
Dart List.where  (0) 2024.01.16
Dart fold 함수  (2) 2023.12.15
Dart mixin  (0) 2023.12.11
getter & setter  (0) 2023.12.09
블로그 이미지

Link2Me

,
728x90

배열.fold()는 배열의 값들을 하나씩 커내 하나의 값으로 변환하는 함수이다.

- curr 는 elememt 이다.

- prev 는 이전값. 최초에는 prev에 0이 들어가고, 다음부터는 return 의 결과값을 prev 에 넣는다.

void main() {
  int totalPrice = [12345].fold(0, (prev, curr) {
    print("$prev / $curr");
    return prev + curr;
  });
  print(totalPrice);
}

 

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

Dart List.where  (0) 2024.01.16
[Dart 고급] Dart asMap, entries  (0) 2024.01.16
Dart mixin  (0) 2023.12.11
getter & setter  (0) 2023.12.09
Dart 직렬화(Serialization) 및 역직렬화(Deserialization)  (0) 2023.12.08
블로그 이미지

Link2Me

,

Dart mixin

Flutter 앱/Dart 언어 2023. 12. 11. 09:23
728x90

Mixin은 " Mixins are a way of defining code that can be reused in multiple class hierarchies. (여러 클래스 계층에서 코드 정의한 부분을 재사용하기 위한 방법 중 하나이다.)" 공식문서에 표현되어 있다. 

https://dart.dev/language/mixins

Dart 언어에는 extends, implements이 주로 사용되며 extends는 클래스를 상속할 때, implements는 추상화 클래스를 만들 때 사용한다.

상속(extends)할 때에는 클래스의 메소드를 override(재정의)하지 않으나, implements를 한 경우에는 반드시 override(재정의)가 필요하다.

Dart에서는 extends를 통한 다중 상속이 지원되지 않는다. mixin은 다중 상속해야 하는 경우에 주로 사용된다.

 

mixin class Scanner {
  // mixin class 키워드는 Dart 3.0.0 버전 이상부터 사용할 수 있다.
  void scanning() => print("scanning...");
}
 
mixin class Printer {
  void printing() => print("printing...");
}
 
class Machine with Printer, Scanner {}
 
void main() {
  final machine = Machine();
  machine.printing();
  machine.scanning();
}
 
/***
 * class Scanner {}       // mixin 불가능 & 인스턴스 생성 가능
 * mixin Scanner {}       // mixin 가능 & 인스턴스 생성 불가능
 * mixin class Scanner {} // mixin 가능 & 인스턴스 생성 가능
 */

 

 

 

 

 

 

 

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

[Dart 고급] Dart asMap, entries  (0) 2024.01.16
Dart fold 함수  (2) 2023.12.15
getter & setter  (0) 2023.12.09
Dart 직렬화(Serialization) 및 역직렬화(Deserialization)  (0) 2023.12.08
Dart 3.0 records  (0) 2023.10.19
블로그 이미지

Link2Me

,
728x90

get 키워드를 사용한 함수를 Getter 라고 부른다.

// 일반 형태
반환타입 get 이름 {
    return 반환값;
}
 
// 화살표 구문 사용
반환타입 get 이름 => 반환값;

 

 

set 키워드를 사용하는 함수를 Setter 라고 부른다.

set 이름(값) {
    // 할당시 수행하고 싶은 로직
}

 

 

 

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

Dart fold 함수  (2) 2023.12.15
Dart mixin  (0) 2023.12.11
Dart 직렬화(Serialization) 및 역직렬화(Deserialization)  (0) 2023.12.08
Dart 3.0 records  (0) 2023.10.19
Dart Collection  (0) 2022.06.28
블로그 이미지

Link2Me

,
728x90

 

JSON(JavaScript Object Notation)은 데이터를 표현하는 규칙이다.

  • 문자열에서 단따옴표('문자열')가 아닌 쌍따옴표("문자열")을 사용해야 한다.
  • 네트워크를 통해 다른 컴퓨터로 데이터 전송할 때 일련의 바이트(문자열)로 전달한다.

역직렬화(Deserialization) : 일련의 문자열 → Dart 클래스
직렬화(Serialization) : Dart 클래스 → 일련의 문자열
역직렬화(Deserialization) 진행 순서

  • JSON 포맷 String → Map<String, dynamic>
  • Map<String, dynamic> → Person 클래스

JSON 포맷 문자열이기 때문에 jsonDecode() 함수를 이용하면 Map<String, dynamic>으로 손쉽게 변경할 수 있다.

 

import 'dart:convert';
 
class Person {
  final String name;
  final int age;
 
  const Person({
    required this.name,
    required this.age,
  });
 
  // factory 키워드를 붙여 생성자 메소드로 만들 수 있으며, 다음 규칙을 지켜야 한다.
  // 클래스 인스턴스를 반환해야 한다.
  // 메소드명을 클래스명.메소드명() 형태로 작성해야 한다.
  factory Person.fromJson(Map<String, dynamic> json) {
    return Person(
      name: json['name'],
      age: json['age'],
    );
  }
 
  // 클래스의 인스턴스를 Map<String, dynamic>으로 변경하는 함수는 
// 일반적으로 클래스에 toJson() 메소드를 만들어 진행한다.
  Map<String, dynamic> toJson() {
    return {
      "name": name,
      "age": age,
    };
  }
}
 
void main() {
  // 네트워크 응답 문자열
  String jsonString = '{"name": "철수", "age": 10}';
 
  // JSON 포맷 String -> Map<String, dynamic>
  Map<String, dynamic> jsonMap = jsonDecode(jsonString);
  print(jsonMap);
 
  // Map<String, dynamic> -> Person
  Person person = Person.fromJson(jsonMap);
  print(person);
 
  // Person -> Map<String, dynamic>
  Map<String, dynamic> personMap = person.toJson();
  print(personMap);
 
  // jsonEncode() 함수를 이용하면 Map<String, dynamic>을 
// JSON 포맷 String으로 변경할 수 있다.
  // Map<String, dynamic> -> JSON 포맷 String
  String personString = jsonEncode(personMap);
  print(personString);
}
 

 

 

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

Dart mixin  (0) 2023.12.11
getter & setter  (0) 2023.12.09
Dart 3.0 records  (0) 2023.10.19
Dart Collection  (0) 2022.06.28
Dart Class(클래스)  (0) 2022.06.27
블로그 이미지

Link2Me

,
728x90

https://dart.dev/language/records 에 공식적인 설명이 되어 있다.

 

Records는 익명성, 불변성, 집계성을 가진 타입이며
다른 컬렉션 유형(List, Set, Map 등등)과 마찬가지로 여러 개체를 하나의 개체로 묶을 수 있다.
하지만 다른 컬렉션 유형과 달리 Record는 크기와 유형이 고정되어 있다.

void main() {
  final result = person({
    'name''홍길동'
    'age'25
  });
  
  print(result); // (홍길동, 25)
  
  print(result.$1); // 홍길동
  
  print(result.$2); // 25
  
  
 
  var record = ('first', a: 2, b: true'last');
 
  print(record.$1); // Prints 'first'
  print(record.a); // Prints 2
  print(record.b); // Prints true
  print(record.$2); // Prints 'last'
 
 
}
 
// 튜플로 반환하여 Type과 순서를 보장받을 수 있다.
// 튜플은 소괄호를 사용한다.
(String, int) person(Map<String, dynamic> json) {
  return (json['name'as String, json['age'as int);
}
 

 

 

 
// Returns multiple values in a record:
(String, int) userInfo(Map<String, dynamic> json) {
  return (json['name'as String, json['age'as int);
}
 
final json = <String, dynamic>{
  'name''Dash',
  'age'10,
  'color''blue',
};
 
// Destructures using a record pattern:
var (name, age) = userInfo(json);
 
/* Equivalent to:
  var info = userInfo(json);
  var name = info.$1;
  var age  = info.$2;
*/

 

 

void main() {
  final result = getPersonWithType();  
 
  for(final item in result){
    print(item);
  }
  
  print('-----------------------');
  
  for(final item in result){
    print(item.$1);
    print(item.$2);
  }
 
}
 
List<(String name, int age)> getPersonWithType() {
  return [
    ('홍길동'25),
    ('강감찬'37),
    ('이순신'33)
  ];
}

 

 

void main() {
  final result = getPersonWithNameType(); 
 
  for(final item in result){
    print(item);
  }
  
  print('-----------------------');
  
  for(final item in result){
    print(item.name);
    print(item.age);
  }
 
}
 
List<({String name, int age})> getPersonWithNameType() {
  return [
    ( name: '홍길동', age: 25),
    ( name: '강감찬', age: 37),
    ( name: '이순신', age: 33)
  ];
}

 

 

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

getter & setter  (0) 2023.12.09
Dart 직렬화(Serialization) 및 역직렬화(Deserialization)  (0) 2023.12.08
Dart Collection  (0) 2022.06.28
Dart Class(클래스)  (0) 2022.06.27
Dart Asynchronous programming(비동기 프로그래밍)  (0) 2022.06.23
블로그 이미지

Link2Me

,
728x90

다트는 List, Map, Set 컬렉션을 제공한다.

 

List

- 순서가 있는 자료를 담는 컬렉션이다.

- 같은 타입의 자료를 여러개 담을 수 있고 특정 인덱스로 접근 가능하다.

 

Map : { key : value }

- key 와 value의 쌍으로 저장할 수 있고, 키를 통해 값을 얻을 수 있다.

- key는 고유한 값이여야 한다. 이미 있는 key에 값을 넣으면 덮어 씌어진다.

void main(){
  var fruits = { //맵 만들기
    'apple''사과',
    'banana''바나나',
    'carrot''당근',
  };
 
  fruits.addAll({
    'pear' : '배',
    'pineapple' : '파인애플',
  });
 
  print(fruits);
 
  fruits.remove('banana'); // 제거
 
  print(fruits.keys.toList()); // key 가져오기
  print(fruits.values.toList()); // values 가져오기
}

 

 

Set

- 중복이 허용되지 않고, 찾는 값이 있는지 없는지 판단하고자 할 때 사용한다.

 

 

 

 

void main(){
  final List<String> Items = ['짜장''짬봉''볶음밥''사천짜장''송이덧밥'];
 
  for(String item in Items){
    print(item);
  }
 
  // map() 메소드는, 사용자가 반환 된 객체에서 항목을 요청할 때까지 함수가 호출되지 않는다.
  final newItems = Items.map((x) => x);
  final newItems1 = Items.map((x) => x);
  print(newItems);
  print(newItems1);
  print(newItems == newItems1); // false
  // 눈에 보이는 결과는 동일하게 보이지만, 각각 객체로 생성되어 서로 다르다.
 
  // // 즉시 반영되도록 하고자 하는 경우에는 toList(), toMap() 메소드를 사용한다.
  final newItems2 = Items.map((x) => x).toList();
  print(Items);
  print(newItems2);
  print(Items == newItems2); // false : 원 Items 와 newItems2 는 다르다.
}

 

void main(){
  // 문자열을 분리하고 map 메소드를 사용하여 새로운 List 만들기
  var numbers = '13579';
  final parsed = numbers.split('').map((e) => '$e.png').toList();
  print(parsed);
}

 

void main(){
  var myList = [0842697];
  var result = myList.where((item) => item > 5).toList();
  print(result); // [6, 8, 7]
  var fst = myList.firstWhere((item) => item > 5);
  print(fst); // 8
  var last = myList.lastWhere((item) => item > 5);
  print(last); // 7
}

 

void main(){
  List<String> names = ['Max''John''Sara''Peter''Charlie'];
  Iterable<String> v_name = names.where((element) => element.contains('a'));
  print(v_name); // (Max, Sara, Charlie)
}

 

void main() {
  final myList = [13549110-4-10];
  final result = myList.reduce((sum, element){
    print('sum : ${sum}, element : ${element}');
    return sum + element;
  });
  print(result);
}

첫번째만 sum, element 가 1과 3이 대입되고, 그 다음부터는 return 결과값이 sum 으로 대입된다.

void main() {
  final myList = [13549110-4-10];
  final result = myList.reduce((max, element){
    //print('max : ${max}, element : ${element}');
    if(max > element){
      return max;
    } else {
      return element;
    }
  });
  print(result);
}

 

fold 는 시작값인 0을 지정한다.

void main(){
  List<int> myList = [13549110-4-10];
  final sum = myList.fold<int>(0, (sum, element){
    //print('sum : ${sum}, element : ${element}');
    // 최초 sum 값에 0 이 대입된다. 이후의 sum 은 return 결과값
    return sum + element;
  });
  print(sum); // result : 19
}

 

class Person {
  final String name;
  final int age;
 
  Person(this.name, this.age);
}
 
List<Person> person = [
  Person('A'10),
  Person('B'20),
  Person('C'30),
  Person('D'40),
  Person('E'50),
  Person('F'60),
];
 
void main() {
  final ages = person.fold<int>(0, (sum, value) => sum + value.age);
  print('$ages'); // result : 210
 
  final names = person.fold<String>('', (sum, value) => sum + value.name);
  print('${names}'); // result : ABCDEF
}

 

 

 

 

스프레드 연산자

... 연산자는 컬렉션을 펼쳐주는 연산자로 스프레드 연산자라고 한다.

다른 컬렉션 안에 컬렉션을 삽입할 때 사용한다.

컬렉션도 타입 추론이 가능하여 일반적으로 var 로 선언한다.

void main() {
  var items = ['짜장''짬봉''볶음밥'];
  print(items);
 
  var data = [...items, '라면''떡볶이''김밥'];
  print(data); // [짜장, 짬봉, 볶음밥, 라면, 떡볶이, 김밥]
}

 

 

 

 

 

 

블로그 이미지

Link2Me

,
728x90

Last Updated : 2023.10.19

 

Dart Class

- this.name 에서 this는 클래스를 의미한다.

- 인스턴스를 생성할 때 new 키워드는 붙여도 되고 붙이지 않아도 된다.

- final 키워드를 사용하여 생성자 생성시 name, leg를 변경하지 못하게 할 수 있다.

- String? _name 처럼 변수명 앞에 _가 붙으면 private를 의미하며, 같은 파일내에서만 private로 동작한다.

  Java는 Class 당 1개의 파일을 생성하는 것을 원칙으로 하고 있어 class 내에서만 private가 동작한다.

- 가시성 : 밑줄로 시작하지 않으면 모든 것이 공개(public)된다.

  자바처럼 public, protected, private 키워드를 별도로 사용하지 않는다.

void main(){
  Animal lion = Animal(name: '사자', leg: 4);
  lion.move();
 
  Animal spider = Animal(name: '거미', leg: 8);
  spider.move();
}
 
class Animal {
  final String name;
  final int leg;
 
  //Animal(this.name, this.leg);
  Animal({required this.name, required this.leg});
 
  void move(){
    print('${this.name}가 ${this.leg}개의 다리로 움직입니다.');
  }
}

 

getter / setter 예제

void main(){
  Animal lion = Animal('사자'4);
  lion.name = '호랑이'// setter
  lion.move();
 
  Animal spider = Animal('거미'8);
  spider.move();
  print(spider.name); // getter
}
 
class Animal {
  String? _name;
  final int leg;
 
  Animal(String name, int leg): this._name= name, this.leg=leg;
 
  // String get name {
  //   return this._name ?? '';
  // }
  String get name => this._name ?? ''// getter
 
  void set name(String name) { // setter
    this._name = name;
  }
 
  void move(){
    print('${this._name}가 ${this.leg}개의 다리로 움직입니다.');
  }
}

 

static 은 인스턴스에 귀속되지 않고 class 에 귀속된다.

class Employee {
  static String? building;
  final String name;
 
  const Employee({
    required this.name,
  });
 
  void workInfo(){
    print('제 이름은 ${name}입니다. ${building} 건물에서 근무중입니다.');
  }
}
 
void main() {
  Employee.building = '르네상스호텔'// static은 class 에 귀속된다.
  Employee seungki = Employee(name: '승기');
 
  seungki.workInfo();
 
  Employee gildong = Employee(name: '길동');
  gildong.workInfo();
}

 

Class Generic

- 제네릭(Generic) : 클래스를 정의할 때, 구체적인 타입(type)을 적지 않고 변수 형태로 적어 놓는 것이다. 
- 클래스를 선언하여 객체를 생성할 때, 구체적인 타입을 기재한다. 즉, 타입을 어떤 클래스 종류의 매개변수로 보는 것이다.

- 제네릭 프로그래밍(Generic Programming) : 작성한 코드를 다양한 타입의 객체에 대해 재사용하는 객체 지향 기법이다.

class Employee<T, V> {
  // Generic : 타입을 외부에서 받을 때
  final T name;
  final V age;
 
  const Employee({
    required this.name,
    required this.age,
  });
 
  void employeeInfo(){
    print('제 이름은 ${name}이고, 나이는 ${age}살 입니다.');
  }
 
  void varType(){
    print('name : ${name.runtimeType}, age : ${age.runtimeType}');
  }
}
 
void main() {
  Employee<Stringint> seungki = Employee(name: '승기', age: 30);
  seungki.employeeInfo();
  print(seungki.runtimeType); // Employee<String, int>
  seungki.varType(); // name : String, age : int
 
  Employee<Stringint> gildong = Employee(name: '길동', age: 35);
  gildong.employeeInfo();
}

 

 

 

If We have a few classes such as a Dog class, Cat Class, Wolf Class, Cow class and a Lion Class.

We can see that all these classes share common behaviors and features. 

All of these classes should have a eat method, sleep method, move method

and a makenoise method and common characteristics such as food.

클래스 상속

- 클래스는 다른 클래스를 상속(Inheritance) 받을 수 있다.

- 상속 받을 때에는 extends라는 키워드를 사용한다.

- Dart에서는 하나의 클래스만 상속이 가능하다.

- 부모 클래스에 접근하기 위해서는 super 키워드를 사용한다.

- 자식 클래스에서 @override 키워드를 사용하여 부모 클래스 메소드를 오버라이드(재정의)할 수 있다.

- 자식 클래스에서 새로운 메소드를 추가할 수 있다.

void main(){
  Animal spider = Animal(name: '거미', leg: 8);
  spider.move();
 
  Cat cat = Cat(name: '고양이', leg: 4);
  cat.move();
  cat.eat();
 
  Dog dog = Dog(name: '개', leg: 4);
  dog.move();
 
  print('------ Type Comparison ---- ');
  print(spider is Animal); // true
  print(spider is Cat); // false
  print(dog is Animal); // true
  print(dog is Dog); // true
}
 
class Animal {
  final String name;
  final int leg;
 
  //Animal(this.name, this.leg);
  Animal({required this.name, required this.leg});
 
  void move(){
    print('${this.name}가 ${this.leg}개의 다리로 움직입니다.');
  }
}
 
class Cat extends Animal {
  Cat({required super.name, required super.leg});
 
  void eat(){
    print('${super.name}가 참치를 맛있게 먹고 있습니다.');
  }
 
}
 
class Dog extends Animal {
  Dog({required super.name, required super.leg});
 
  @override
  void move() {
    //super.move();
    print('${super.name}가 ${super.leg}개의 다리로 힘차게 달립니다.');
  }
}

 

인터페이스

- Dart에서는 Interface라는 키워드 대신 class를 사용하여 인터페이스를 정의한다.

- Dart 3.0 부터는 interface class로 선언할 수 있으며 implement만 가능하다.

- 인스턴스 생성을 못하게 abstract 키워드를 붙이고, 메소드 정의만 하도록 한다.

- 인터페이스 구현은 implements 를 사용한다.

abstract class Food {
  String? name;
  void printName(); // 메소드 정의
}
 
class Fruit implements Food {
  String? name;
 
  Fruit(String name) : this.name = name;
 
  void printName() { // 메소드 구현
    print('Fruit name is ${this.name}!');
  }
 
}
 
void main() {
  Fruit fruit = Fruit('Apple');
  fruit.printName();
}

 

 

클래스 확장, 인터페이스 구현, 추상 클래스 외에도 다트는 믹스인(mixin) 개념을 제공하고 여기서 with 키워드를 사용한다.

 

Mixins

- 믹스인은 여러 클래스 계층에서 클래스의 코드를 재사용하는 방법이다.
- with 키워드를 사용하면 상속하지 않고 다른 클래스의 기능을 가져오거나 override 할 수 있다.
- 믹스인을 구현하려면 생성자를 선언하지 않는 클래스를 만든다.
- 믹스인을 일반 클래스로 사용하려면 class 대신 mixin 키워드를 사용한다.

abstract class Super {
  void method() {
    print("Super");
  }
}
 
class MySuper implements Super {
  void method() {
    print("MySuper");
  }
}
 
mixin Mixin on Super {
  void method() {
    super.method();
    print("Sub");
  }
}
 
class Client extends MySuper with Mixin {}
 
void main() {
  Client().method();
}
/* 실행 결과
MySuper
Sub
*/

참고 : https://medium.com/flutter-community/dart-what-are-mixins-3a72344011f3

 

 

Dart 3.0 변경 사항

- final로 클래스를 선언하면 extends, implement, mixin 으로 사용이 불가능하다.

- base로 선언하면 extends는 가능하지만 implement는 불가능하다.

- base, sealed, final로 선언된 클래스만 extend가 가능하다.

- interface로 선언하면 implement만 가능하다.

- sealed 클래스는 adstract이면서 final이다.

  또한 sealed 클래스는 패턴 매칭을 사용할 수 있도록 해준다.

- mixin 클래스로 선언 하여 사용할 수 있다.(mixin과 동일한 특성)

  • extends나 with를 사용할 수 없다.
  • on 키워드를 사용 할 수 없다.

 

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

Dart 3.0 records  (0) 2023.10.19
Dart Collection  (0) 2022.06.28
Dart Asynchronous programming(비동기 프로그래밍)  (0) 2022.06.23
Dart function(함수)  (0) 2022.06.22
Dart Type 검사(is, is!)  (0) 2022.06.22
블로그 이미지

Link2Me

,
728x90

요즈음은 비동기 프로그래밍이 기본이다.

다트에서 비동기에 관련된 핵심 클래스는 Future 와 Stream 이며, async 와 await 키워드와 함께 사용한다.

다트 코드는 단일 쓰레드에서 실행된다.

 

Future 클래스

비동기 함수는 Future 클래스를 리턴한다. 이 Future 클래스는 미래에 비동기 작업이 끝나면 값을 받아오는 클래스이다
Future클래스에는 콜백을 2개 등록할 수 있다.
 - 비동기 함수가 성공시 성공에 대한 콜백
 - 비동기 함수가 error가 발생 시 exception을 일으키는 콜백

Future는 두가지의 state를 가진다.
 - Uncompleted, 비동기 함수가 아직 끝나지 않은 상태
 - Completed, 비동기 함수가 작업이 끝난 상태. 성공하면 value를, 실패하면 error 값을 가져온다

Future<T>는 비동기 처리가 성공시 T타입의 값을 가져온다. 만약 T가 String이면 Future<String> 으로 적어준다.
값을 리턴하지 않을 경우 Future<void> 라고 적는다.

void main(){
  print('Before the Future');
  Future((){
    print('Running the Future');
  }).then((_) => print('Future is complete.') );
  print('After the Future');
 
  /*
  1. 다트에 의해서 future 객체가 내부적인 배열에 등록
  2. Future 관련해서 실행되어야 하는 코드들이 이벤트 Queue 에 등록
  3. 불완전한 future 객체 반환
  4. Synchronous 방식으로 실행되어야 할 코드 먼저 실행
  5. 최종적으로 실제적인 data 값이 future 객체로 전달
  */
 
  /* 실행 결과
  Before the Future
  After the Future
  Running the Future
  Future is complete.
   */
}

Future의 then(), catchError() 함수

then() 함수를 통해 Future가 complete 되면 실행해줄 콜백을 등록할 수 있다.
또한 catchError() 함수를 통해 에러처리를 해줄 수 있다.

 

 
String createOrderMessage(){
  var order = fetchUserOrder();
  return 'Your order is : ${order}';
}
 
Future<String> fetchUserOrder(){
  return Future.delayed(
    Duration(seconds: 2),
      () => 'Large Latte',
  );
}
 
void main(){
  print('Fetching user order...');
  print(createOrderMessage());
}
 
/* 실행결과
Fetching user order...
Your order is : Instance of 'Future<String>'
*/

원하지 않은 결과가 출력되었다.

 

 

async : async 함수 본문 앞에 키워드를 사용하여 비동기로 표시할 수 있다.
async function : async 함수는 async 키워드로 표시된 함수다.
await : await 키워드를 사용하여 비동기식의 완성된 결과를 얻을 수 있다.

await 키워드는 단지 async 내에서 작동하는 기능이다.

 

Async method

- 메소드를 통해 나오는 결과물은 Future

- await 키워드를 만날 때까지 synchronous 방식으로 코드 처리

- await 키워드를 만나면 future 가 완료될 때까지 대기

- future 가 완료되자마자 그 다음 코드들을 실행

 

코드를 아래와 같이 수정한다.

future가 완료될 때까지 일시 중단하려면 async 함수에서 await를 사용하면 된다.

Future<String> createOrderMessage() async {
  print('synchronous');
  var order = await fetchUserOrder();
  return 'Your order is : ${order}';
}
 
Future<String> fetchUserOrder(){
  return Future.delayed(
    Duration(seconds: 2),
      () => 'Large Latte',
  );
}
 
void main() async {
  print('Fetching user order...');
  print(await createOrderMessage());
}
 
/* 실행 결과
Fetching user order...
synchronous
Your order is : Large Latte
*/

이제 원하는 결과가 출력되었다.

 

 

void main() async {
  methodA();
  await methodB();
  await methodC("main");
  methodD();
}
 
void methodA() {
  print('A method run.');
}
 
methodB() async {
  print('B method start.');
  await methodC('B');
  print('B method end.');
}
 
methodC(String s) {
  print('C method start FROM ${s}');
  Future(() => print('C Future running FROM ${s}'))
      .then((_) => print('C Future is complete FROM ${s}'));
  print('C method end FROM ${s}');
}
 
void methodD() {
  print('D method run.');
}
 
/* 실행결과
A method run.
B method start.
C method start FROM B
C method end FROM B
B method end.
C method start FROM main
C method end FROM main
D method run.
C Future running FROM B
C Future is complete FROM B
C Future running FROM main
C Future is complete FROM main
*/

 

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

Dart Collection  (0) 2022.06.28
Dart Class(클래스)  (0) 2022.06.27
Dart function(함수)  (0) 2022.06.22
Dart Type 검사(is, is!)  (0) 2022.06.22
Dart const, final  (0) 2022.06.22
블로그 이미지

Link2Me

,
728x90

본 게시글 작성 시점은 Null safety 가 적용된 이후 시점이라 Named Optional Parameters 부분이 다른 블로그/구글자료와   다를 수 있다.

  • Edit the package’s pubspec.yaml file, setting the minimum SDK constraint to 2.12.0:
environment:
  sdk: '>=2.12.0 <3.0.0'

 

 

Dart는 객체 지향 언어이다. Dart에서는 모든 것이 객체이기 때문에 함수도 객체이다.

함수가 객체이기 때문에 변수가 함수를 참조할 수 있다. 함수의 인자로 함수를 전달할 수 있다.

 

int add(int a, int b) {
  return a + b;
}
 
void main() {
  int x = 4;
  int y = 5;
 
var z = add(x, y); // 객체이기 때문에 함수를 참조할 수 있다.
 
  print("Output: $z");
}

 

 

int add(int a, int b) {
  return a + b;
}
 
// return_type func_name(parameters) => expression;
int sub(int a, int b) => a - b; // 람다식 표현
 
// Lambda functions are also called Arrow functions.
int mul(int a, int b) => a * b ; 
 
void main() {
  int x = 10;
  int y = 5;
 
  var z = add(x, y); // 객체이기 때문에 함수를 참조할 수 있다.
  print("Output: $z"); // Output: 15
 
  print('${x + y} X ${x - y} = ${mul(add(x,y), sub(x,y))}');
  // 15 X 5 = 75
}

변수 앞에 $ 기호를 붙여 문자열 내에 변수를 삽입할 수 있다.

또한 $ 기호 뒤에 {}로 둘러싸 수식을 포함한 각종 표현식을 사용할 수 있다.

함수의 인자로 함수를 전달한 것을 확인할 수 있다.

 

 

선택 매개변수

함수 호출 시 매개변수명을 이용하여 인자 값을 넘겨줄 수 있다. 매개변수명으로 인자 값을 넘겨줄 때 {매개변수명: value}로 해줘야 한다.

// Ordered Optional Parameters
void printSomething(int a, int b, [int c = 99]){
  // 필수 매개변수와 선택 매개변수를 함께 사용하고 싶다면
  // 필수 매개변수를 앞에 둔다.
  print(a + b + c);
}
 
// Named Optional Parameters
void namedSomething(int a, int b, {int c = 99}){
  print(a + b + c);
}
 
// Named Optional Parameters
void person({required String name, int age = 0}){
  print('${name}, ${age}');
}
 
class Person {
  String name;
  int age;
 
  Person({required this.name, required this.age });
}
 
main(){
  printSomething(2,3);
  printSomething(2,3,5);
 
  namedSomething(2,3);
  namedSomething(2,3,c : 10);
 
  person(name: '홍길동', age: 25); // OK
  person(name: '홍길동'); // OK
  // person(); // error
 
  // Class 에 객체 할당
  Person p = Person(name: '홍길동', age: 30);
  print('${p.name}, ${p.age}');
}

Java 는 선택 인자를 제공하지 않는다. 따라서 선택 인자를 구현하기 위해서는 오버로딩으로 별도로 2개 함수를 작성해야  한다.

이름 있는 인자는 Python 에서도 제공하는데 필수 인자와 선택 인자 모두 이름을 넣을 수 있는 반면,

다트에서는 선택 인자에만 이름을 넣을 수 있다.

 

 

null safety 가 적용되어 Named Optional Prameters를 사용하고자 한다면

String 지시어에 ? 가 없으면 반드시 required 를 붙이도록 하고 있다.

// Named Optional Parameters
void person({required String name, int age = 0}){
  print('${name}, ${age}');
}
 
void person1({String? name, int? age}){
  print('${name}, ${age}');
}
 
void person2(String name, {int? age}){
  // 다트에서는 모든 것이 객체이기 때문에
  // 초기값이 설정되지 않는 것은 0 이 아니라 null 이다.
  print('${name}, ${age}');
}
 
main(){
  person(name: '홍길동', age: 25); // 홍길동, 25
  person(name: '홍길동'); // 홍길동, 0
  // person(); // error
 
  person1(name: '홍길동', age: 30); // 홍길동, 30
  person1(name: '홍길동'); // 홍길동, null
  person1(age: 30); // null, 30
  person1(); // null, null
 
  person2('홍길동'); // 홍길동, null
  person2('홍길동', age: 28); // 홍길동, 28
}

 

// Named Optional Parameters
void person({String name=''int age = 0}){
  // {} 파라미터를 사용하면 반드시 초기화된 값이나 required 가 필요하다.
  print('${name}, ${age}');
}
 
main(){
  person(name: '홍길동', age: 25); // 홍길동, 25
  person(name: '홍길동'); // 홍길동, 0
  person(age: 25); // , 25
  person(); // , 0
}

 

익명함수 및 람다식

익명함수의 기본 형태는 다음과 같다.

(매개변수명) { 표현식; }

 

람다식의 형태는 다음과 같다.

(매개변수명) => 표현식; // Javascript 에서는 화살표 함수라고 한다.

 

다트에서 대부분의 함수는 이름을 가지고 있다. 이름 없는 함수로 알려진 익명 함수를 생성할 수 있다.

다트에서 이름이 없는 함수를 익명함수, 람다, 또는 클로저(closure)라고 부른다.

void printElement(int element) {
  print(element);
}
 
main(){
  var list = [123];
 
  // Pass printElement as a parameter.
  list.forEach(printElement); // 함수명을 매개변수로 전달
 
  /* 익명함수(Anonymous Functions) 문법
  (parameter_list){
   statement(s); // 함수 구현부
  }
  */
  const List = ['apples''bananas''oranges'];
  List.forEach((item) {
    print('${List.indexOf(item)}: $item');
  });
  // 만약 익명함수가 한줄이거나 return문이 한줄일 경우 중괄호를 화살표로 바꿔줄 수 있다.
 
  // (파라미터) => 한줄짜리 함수문장;
  list.forEach((item) => print('${list.indexOf(item)}: $item'));
  // The above example defines an anonymous function with an untyped parameter, item.
  // The function, invoked for each item in the list,
  // prints a string that includes the value at the specified index.
}

 

 

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

Dart Class(클래스)  (0) 2022.06.27
Dart Asynchronous programming(비동기 프로그래밍)  (0) 2022.06.23
Dart Type 검사(is, is!)  (0) 2022.06.22
Dart const, final  (0) 2022.06.22
Dart 변수 var, dynamic, num, int, double  (0) 2022.06.22
블로그 이미지

Link2Me

,
728x90

The instanceof-operator is called is in Dart.

is : 같은 타입이면 true

is! : 다른 타입이면 true

 

main() {
  int x = 10;
  // is 키워드를 사용하면, 해당 참조가 주어진 타입인지 검사
  if(x is int){
    print('정수');
  }
}

 

void main() {
  var value = 2;
  print(value is int);
  print(value is! int);
}

 

 

class Foo {
  @override
  Type get runtimeType => String;
}
 
main() {
  var foo = Foo();
  if (foo is Foo) {
    print("It's a foo!");
  }
  print("Type is ${foo.runtimeType}");
}

 

 

To check the type of a variable in Flutter and Dart, you can use the runtimeType property.

플러터와 다트에서 변수의 타입을 검사하기 위해, runtimeType 프로퍼티를 사용할 수 있다.

void main(){
  var a = 'Apple';
  var b = 100;
  var c = [12345];
  var d = {
    "name""John Doe",
    "age" : 40
  };
  var e = 1.14;
  
  print(a.runtimeType);
  print(b.runtimeType);
  print(c.runtimeType);
  print(d.runtimeType); 
  print(e.runtimeType);
}

 

class Person {
  var s = '홍길동';
  var d = 5.5;
  var r = true;
}
 
main() {
  Person p = Person(); // new 생략 가능
  print('Data type of s : ${p.s.runtimeType}');
  print('Data type of d : ${p.d.runtimeType}');
  print('Data type of r : ${p.r.runtimeType}');
}

 

class Shape {
  String color;
  Shape({required this.color}); // 생성자
}
 
class Circle extends Shape {
  double radius;
  Circle({color, required this.radius}) : super(color: color);
}
 
class Rectangle extends Shape {
  double length;
  double width;
  Rectangle({color, required this.length, required this.width}) : super(color: color);
}
 
void main() {
  Circle circle = Circle(color: 'red', radius: 10);
 
  print(circle is Circle); // true
  print(circle is Shape); // true
  print(circle is Rectangle); // false
}

참조 : https://www.woolha.com/tutorials/dart-getting-runtime-type-of-object

 

 

assert() 함수는 계산 결과가 참인지 거짓인지 검사한다.

https://dartpad.dartlang.org/ 사이트에서는 동작되지 않더라.

 

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

Dart Class(클래스)  (0) 2022.06.27
Dart Asynchronous programming(비동기 프로그래밍)  (0) 2022.06.23
Dart function(함수)  (0) 2022.06.22
Dart const, final  (0) 2022.06.22
Dart 변수 var, dynamic, num, int, double  (0) 2022.06.22
블로그 이미지

Link2Me

,
728x90

둘 다 불변의 상수를 의미하는 keyword 이지만 const 가 더욱 불변의 강도가 강하다.

final : final 지시어는 어떤 변수를 참조하는 값이 한번 설정되면 다른 값으로 변경될 수 없다는 것을 의미한다.

          run-time constant 이며, APP 실행과정에서 값이 정해진다.

const : 한번만 설정할 수 있지만 compile-time constant로 컴파일 타임에 그 값을 알 수 있어야 한다.

            Java 언어에서는 public static final 이라는 복잡한 키워드를 사용하지만,

            다트 언어에서는 const 로 단순화할 수 있다.

 

void main() {
 String name1 = '홍길동';
 print(name1);
  
 const String name2 = '홍길동'
 print(name2);
  
 final String name3 = '홍길동'
 print(name3);
  
}

 

 

void main() {
  final name = '홍길동'// 타입 생략 가능
  print(name);
}
 

 

 

void main() {
 String name1 = '홍길동';
 name1 = '이순신';
 print(name1);
  
 const String name2 = '홍길동'
 name2 = '이순신'// 에러
 print(name2);
  
 final String name3 = '홍길동'
 name3 = '이순신'// 에러
 print(name3);
  
}

 

The Const keyword in Dart behaves exactly like the final keyword. 

The only difference between final and const is that the const makes the variable constant from compile-time only. Using const on an object, makes the object’s entire deep state strictly fixed at compile-time and that the object with this state will be considered frozen and completely immutable.

void main() {
  final x1 = DateTime.now();
  print(x1);
  
  // Error: Cannot invoke a non-'const' constructor where a const expression is expected.
  const x2 = DateTime.now(); // 컴파일 타임에 값을 알 수 없어 에러 발생
}

DateTiem.now()는 APP 실행시 정해지는 값이다.

 

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

Dart Class(클래스)  (0) 2022.06.27
Dart Asynchronous programming(비동기 프로그래밍)  (0) 2022.06.23
Dart function(함수)  (0) 2022.06.22
Dart Type 검사(is, is!)  (0) 2022.06.22
Dart 변수 var, dynamic, num, int, double  (0) 2022.06.22
블로그 이미지

Link2Me

,
728x90

다트(dart) 언어는 https://dartpad.dartlang.org/ 에서 연습하면 된다.

IntelliJ IDEA community 툴을 사용하는 경우에는 https://link2me.tistory.com/2208 게시글을 참조하면 Dart 를 이용할 수 있다.

 

다트(dart) 문법은 main() 함수가 진입점(entry point)이다.

 

다트(dart)의 모든 것은 객체(object)이다.

다트의 변수는 참조(reference)를 저장한다.

 

다트에서는 변수 선언을 두가지 방법으로 할 수 있다.

var x;  // x가 숫자 타입인 경우에도 x의 값은 0이 아니라 null 이다.

String x; // <어떤 특정 타입> x;

 

다트는 정적 타입과 동적 타입(var, dynamic) 둘다 제공한다.

변수명 앞에 타입을 선언한다.

변수 종류를 Type 또는 자료형이라고 한다.

var는 할당을 통해 타입이 결정되면 그 이후에는 타입을 변경할 수 없다. 따라서 진정한 의미에서 동적 타입은 아니다.

우변 변수나 데이터의 타입을 신경쓰지 않아도 다트 컴파일러에서 추론한다.

 

var 타입은 최초 할당된 값을 참고하여 해당 변수의 타입을 추론한다.

void main() {
 var x = 10// 타입추론으로 x 가 int 형으로 설정된다.
 print(x);
 x = 5.5// 정수형으로 결정된 x 변수에 double 형을 할당 불가
 print(x);
}

 

int 와 double은 모두 num 의 서브클래스이다.

void main() {
 num x = 10// num 은 int 와 double 의 상위 클래스
 print(x);
 x = 5.5// double 형 할당 가능
 print(x);
}

final num x = 10;

final 지시어는 어떤 변수를 참조하는 값이 한번 설정되면 다른 값으로 변경될 수 없다는 의미이다.

 

 

dynamic 은 x가 시간에 따라 참조하는 내용이 변경될 수 있음을 다트에게 알려준다.

또는 최상위 클래스인 Object 를 사용해도 된다.

void main() {
 dynamic x = 10
 print(x);
 x = 5.5// double 형 할당 가능
 print(x);
}

 

int 와 double 클래스의 toString() 메소드를 사용해 숫자를 문자열로 바꿀 수 있다.

void main() {
 int x = 10// 정수형
 double y = 5.5// 실수형
 String sx = x.toString(); // 문자열
 String sy = y.toString(); // 문자열
 
 print(x);
 print(y);
 print(sx);
 print(sy);
}

 

int 와 double 클래스의 parse() 메소드를 사용해 문자열을 숫자로 바꿀 수 있다.

void main() {
 String sx = '10'
 String sy = '5.5'
 int x = int.parse(sx); 
 double y = double.parse(sy); 
 
 print(sx);
 print(sy);
 print(x);
 print(y);
}

 

null 을 할당할 수 있다.

void main(){
    double? number = 4.0;
    print(number);
 
    number = 2.0;
    print(number);
    
    number = null;
    print(number);
    
    number ??= 3.0// number가 null 이면 3.0으로 결과를 반환하라.
    print(number);
 
}

 

 

 
void main(){
    int number = 1;
 
    print(number is int);
    print(number is String);
 
    print(number is! int);
    print(number is! String);
}

 

 

'Flutter 앱 > Dart 언어' 카테고리의 다른 글

Dart Class(클래스)  (0) 2022.06.27
Dart Asynchronous programming(비동기 프로그래밍)  (0) 2022.06.23
Dart function(함수)  (0) 2022.06.22
Dart Type 검사(is, is!)  (0) 2022.06.22
Dart const, final  (0) 2022.06.22
블로그 이미지

Link2Me

,