본문으로 바로가기

dart 기본기

category Programming Language/🎯 Dart 2021. 12. 20. 00:02
Dart SDK version: 2.15.1 (stable) (Tue Dec 14 13:32:21 2021 +0100) on "macos_x64" 기준으로 작성되었습니다.

 

변수 초기화

var firstName = "Darren"; // var로 선언시 type infer됨
String lastName = "Kwon"; // 직접 타이핑 가능

 

미할당시

main() {
  int? num;
  print(num); // null
}

 

plugin 사용

import "dart:io";

main() {
  stdout.write("Enter your name: ");
  String? name = stdin.readLineSync();
  print("Hello, $name!");
}

 

dart의 Primitive type들 (int, double, String, bool, dynamic)

main() {
  // dart의 기본 타입 : int, double, String, bool, dynamic
  int a = 100;
  var b = 200; // type infer
  print("$a, $b");

  double c = 3.14;
  var d = 1.14; // type infer

  String e = 'Hello';
  var f = 'World'; // type infer

  bool g = true;
  var h = false; // type infer

  dynamic i = 100; // runtime에 타입이 정의됨.
  i = "Hello"; // dynamic은 형이 다르게 할당할 수 있음
}

 

dynamic 타입의 런타임 타입 출력

main() {
  dynamic a = 5;
  print(a.runtimeType); // int

  a = "string";
  print(a.runtimeType); // String
}

 

raw string

main() {
  String s = r'hello \n wow .... \t hehkekekke'; // raw string은 \n과 같은 이스케이프도 문자 처리함
  print(s);
}

 

type conversion

// assert : https://dart.dev/guides/language/language-tour#assert
// assert는 디버깅 함수이다. 조건식이 거짓인 경우 오류 메시지를 출력한다.
// flutter 에선 개발 모드일 때, 일반 dart일 땐 dart --enable-asserts [path] 꼴로 실행해야 함
main() {
  // String -> int
  var one = int.parse('1');
  assert(one == 1, 'one is not int type');

  // String -> double
  var float = double.parse('1.1');
  assert(float == 1.1, 'float is not double type');

  // int -> String
  String str = 123.toString();
  assert(str == '123', 'str is not string type');

  // double -> String
  String str2 = 1.141592.toStringAsFixed(2); // 소수점 2자리 절삭
  assert(str2 == '1.14', 'str2 is not string type');
}

 

constant

main() {
  const num = 0;
  const a = true;
  const b = 'string';

  num = 5; // Constant variables can't be assigned a value.

  print(num.runtimeType); // int
  print(a.runtimeType); // bool
  print(b.runtimeType); // String
}

 

operator : 우리가 관습적으로 사용하는게 다 된다.

main() {
  int a = 1 + 2; // 3
  a = a - 2; // 1
  a++; // 2
  ++a; // 3
  
  print(a == 3);
  print(a != 3);
  print(a > 3);
  print(a < 3);
  print(a >= 3);
}

 

null aware operator (?. ?? ??=)

// javascript
const a = {name: "darren"}
const b = a?.age ?? null // b는 null이 된다.

// dart에서도 같은 문법이 가능
int number = n?.num ?? 0;
var number = null;
print(number ??= 100); // number가 null이므로 100할당
print(number);

 

ternary operator

main() {
  int n = 100;
  n > 100 ? print('n is greater than 100') : print('n is less than or equal to 100');
}

 

type checking

main() {
  var x = 100;

  print(x is int); // true
  print(x is String); // false
}

 

conditional statement : 너무 직관적이고 우리가 사용하는 그대로이다.

main() {
  var a = 100;

  if (a > 1000) {
    print("wow");
  } else if (a > 100) {
    print("amazing");
  } else {
    print("should prin there");
  }
}

 

switch statement

main() {
  var a = 100;

  switch (a) {
    case 101:
      print("impossible");
      break;
    case 100:
      print("should print here");
      break;
    default:
      print("impossible");
  }
}

 

for loop

main() {
  for (var i = 0; i < 3; i++) {
    print(i);
  }

  for (var j in [10, 11, 12]) {
    print(j);  
  }
  
  for (var i = 0; i < 10; i++) {
    if (i % 2 == 0) continue;
    print(i);
  }

  [100, 101, 102].forEach((element) { 
    print(element); 
  });
}

 

while

main() {
  int num = 0;

  while (num < 3) {
    print(num);
    num++;
  }
}

 

collections: list, set, map

main() {
  List<int> list = [1, 2, 3];
  List<dynamic> dynamicList = [1, 2, "he"];
  List<int> constantList = const [1, 2]; // unmodifiable list. 즉, 변경 불가능한 list

  var list2 = list; // reference 참조 
  var deppcopiedList = [...list]; // shallow copy

  list2.add(4);
  print(list); // list2에 추가했음에도 원본 변형. [1, 2, 3, 4]
  print(deppcopiedList); // 다른 참조값이므로 원본 유지 [1, 2, 3]
}
main() {
  Set<int> a = {1, 2, 3, 4, 3, 2, 1};
  print(a); // 중복이 제거된 {1, 2, 3, 4}

  var b = a; // reference 참조
  var c = {...a}; // shallow copy
  b.add(5);

  print(a); // 원본도 변경됨 {1, 2, 3, 4, 5}
  print(c); // 다른 reference 참조이므로 그대로 {1, 2, 3, 4}
}
main() {
  Map<String, int> map = {"one": 1, "two": 2};
  print(map['one']);

  var copiedMap = map; // reference 참조
  var newMap = {...map}; // shallow copy

  copiedMap.clear(); // 싹 다 지우기
  print(map); // 원본에도 영향
  print(newMap); // 다른 reference 참조로 변화 없음 {one: 1, two: 2}
}

 

List에 대해서 좀 더 알아보자

void main() {
  List a = [1, 2, 3, 4, 5, 6];
  print(a.first);
  print(a.last);
  print(a.isEmpty);
  print(a.isNotEmpty);
  print(a.length);
  print(a.reversed); // ReversedListIterable

  a.add(7); // 하나만 넣기
  a.addAll([8, 9, 10]); // 배열 넣기
  a.remove(1); // 제거
  print(a);
}
void main() {
  List members = [
    {'id': 0, 'name': 'darren'},
    {'id': 1, 'name': 'anold'}
  ];

  List numbers = [10, 20, 30, 40];

  var zeroMember = members.firstWhere((member) => member['id'] == 0); // 원소 찾기
  print(zeroMember);

  var oneMember = members.indexWhere((member) => member['id'] == 1); // index 반환
  print(oneMember);

  var number = numbers.indexOf(30); // 30의 index 반환
  print(number);

  var hasTen = numbers.contains(10); // 10이 있는지 여부
  print(hasTen);
}

 

map의 update가 독특하다

void main() {
  Map items = {
    "brain": "coding",
    "phone": "iPhone"
  };

  items.update("shoes", (prev){return "wow";}, ifAbsent: () {return "you don't have shoes";});

  print(items);
}

 

 

function

main() {
  print(square.runtimeType); // (dynamic) => int. 함수의 타입도 찍어볼 수 있다.
  print(printSomething.runtimeType); // (dynamic) => void

  int result = addTwo(square(2));
  printSomething(result);
}

int square(var num) {
  return num * num;
}

int addTwo(int a) => a + 2; // arrow function이 가능하다.

void printSomething(var msg) => print(msg);

 

named parameters ({})와 optional parameters ([]) 

1. 일반적으로 우리가 쓰는 건 positional parameters다. 위치에 기반하기 때문이다.

2. 위치가 아닌 이름으로 구별하고 싶다면 named parameters를 사용하면 된다.

3. optional parameters는 positional parameters이면서도 단순히 옵셔널하게끔 만들 수 있다.

4. named parameters와 positional optional parameters 둘 다 사용하면 optional이라 기본값 지정 혹은 null handling이 필요.

main() {
  sum(1, 2);
  sum2(a: 1, b: 2); // named parameters
  sum3(1, b: 2);
  sum4(1); // positional optional parameters
}

int sum(int a, int b) => a + b;
int sum2({int a = 0, int b = 0}) =>
    a + b; // named parameters는 optional이다. 따라서 기본값을 지정하거니 null handling이 필요.
int sum3(int a, {int b = 0}) => a + b; // 부분적으로 named parameters를 사용할 수 있다.
int sum4(int a, [int b = 0]) => a + b; // positional optional parameters

 

exception과 try/catch/finally

// Exception 던지기
int shouldGreaterThanZero(int val) {
  if (val > 0) {
    return val;
  } else {
    throw Exception('value should greater than zero');
  }
}

// try/catch/finally
void verifyValue(var val) {
  var verifiedValue;

  try {
    verifiedValue = shouldGreaterThanZero(val);
  } catch (e) {
    print("error occured: $e");
  } finally {
    print(verifiedValue);
  }
}

 

final와 const

final : 런타임에 값이 지정이 되어도 상관 없음.
const : 컴파일타임에 값이 꼭 지정되어야 한다. -> 빌드 타임에 값이 정해져 있어야지, 런타임 돈 이후에 알게 되는 값은 안된다.
공통점 : 둘 다 상수라서 초기화 이후 변경이 불가능함.

main() {
  final name = 'test';
  final String name2 = "wow";
  const name3 = "ama";
  const String name4 = "ddd";
  
  final now = new DateTime.now(); // 런타임에 할당되어 괜찮으니 에러가 아님
  const now2 = new DateTime.now(); // 컴파일 시점에 알수가 없음. DateTime이 돌아야 알 것 아니냐. 그래서 에러임
}

 

enum

enum Status {
  loading,
  fetched,
  done,
  error,
}

main() {
  Status status = Status.loading;

  switch (status) {
    case Status.loading:
      print('로딩중');
      break;
    case Status.fetched:
      print('페칭중');
      break;
    default:
      print('불가능');
  }
}

 

'Programming Language > 🎯 Dart' 카테고리의 다른 글

null safety  (0) 2022.01.03

darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체