플러터 배우면서 정리해보는 Dart 문법

JH Bang·2023년 5월 23일
0

플러터

목록 보기
1/2
post-thumbnail

var 와 dynamic

Dart에는 var 타입과 dynamic 타입이 존재
var 타입에는 아무 자료형이나 넣을 수 있지만, 첫 자료형 타입으로 고정시켜 준다.
반면 dynamic 타입은 아무 자료형이나 막 바꿔서 넣어줄 수 있다.

var name = "jinhyeok";
name = 123;

이렇게 하면 컴파일 에러가 난다.

dynamic name = "jinhyeok";
name = 123;

이렇게 하면 괜찮다.

이 외 기본 자료형은
int, String, double, bool 등등이 있다.

List, Map 자료형

List, Map은 그냥 써도 되고, < > 제너릭을 넣어서 선언해도 된다.

List nums = [5, 4, 3, 2, 1];

// 또는

List<int> nums = [5, 4, 3, 2, 1];
  Map dics = {
    "cat" : "성격이 드러운 애완동물",
    "dog" : "성격이 온순한 애완동물",
  };
  
  // 또는
  
  Map<String, String> dics = {
    "cat" : "성격이 드러운 애완동물",
    "dog" : "성격이 온순한 애완동물",
  };
  

List 선언 시

List myList = [];

List myList = new List();

두 가지 방식으로 선언이 가능한데, new List()에 특정 수를 입력하면 List의 길이를 제한할 수 있다.

List myList = new List(5);

fianl vs const

const는 build time에 값이 정해져 있어햐 한다.
반면 final은 run time에 값이 결정된다

void main() {
  final now1 = new DateTime.now();  // 가능
  
  const now2 = new DateTime.now();  // 불가능
}

for loop

for (int i = 0; i < 10 ; i++) // 첫번째 방법


List<int> items = [1, 2, 3, 4, 5];
for (item in items) // 두번째 방법

continue/break

void main() {
  for (int i = 0; i < 5; i++) {
    if (i == 3) {
      continue;
    }
    print('hello ${i}');
  }
}

...

void main() {
  int i = 0;
  while(i < 5) {
    if (i == 3) {
      i++;
      continue;
    }
    print('hello $i');
    i++;
  }
}

...
/* 결과
hello 0
hello 1
hello 2
hello 4
*/
void main() {
  for (int i = 0; i < 5; i++) {
    if (i == 3) {
      break;
    }
    print('hello ${i}');
  }
}

...

void main() {
  int i = 0;
  while(i < 5) {
    if (i == 3) {
      break;
    }
    print('hello ${i}');
    i++;
  }
}

...

/* 결과
hello 0
hello 1
hello 2
*/

collection if

var nav = ['Home', 'Furniture', 'Plants', if (promoActive) 'Outlet'];

collection for

var listOfInts = [1, 2, 3];
var listOfStrings = ['#0', for (var i in listOfInts) '#$i'];

함수 Optional Params/default 인자

void main() {
  double result1 = add(1,2);
  
  print(result1);
  
  double result2 = add(1,2,0);
  
  print(result2); 
}

double add(double x, double y, [double z = 100]) {
  return (x + y + z);
}

//[dobule z]로만 하면 옵셔널

이를 named parameter 방식으로도 바꿀 수 있다.

void main() {
  double result1 = add(1,2);
  
  print(result1);
  
  double result2 = add(1,2, z: 0);
  
  print(result2); 
}

double add(double x, double y, {double z = 100}) {
  return (x + y + z);
}

typedef

void main() {
  int res1 = calculator(2,3,add);
  int res2 = calculator(2,3,sub);
  
  print(res1); // 5
  print(res2); // -1
}


typedef Operation(int x, int y);

int add(int x, int y) {
  return (x + y);
}

int sub(int x, int y) {
  return (x - y);
}

int calculator(int x, int y, Operation op) {
  return op(x, y);
} 

Class

참고로 private 변수를 선언할때는 _(under bar)를 붙여준다. 다만 private 변수는 파일 단위에서 공유되기 때문에 같은 파일에서는 public 변수처럼 사용된다.

class Person {
  final name;
  final age;
  
  Person(String name, int age)
    : this.name = name,
      this.age = age;

  void introduce() {
    print('안녕하세요, 제 이름은 $name이고, 나이는 $age살입니다.');
  }
}

void main() {
  Person person = Person('홍길동', 25);
  person.introduce();
}

fromMap을 사용해 초기화

fromMap을 이용해 생성자 초기화 리스트를 정의하는 방법은 데이터베이스에서 읽은 데이터나 네트워크를 통해 받은 데이터를 Dart 객체로 변환할 때 사용하는 방법이다. fromMap 메서드는 Map 타입의 데이터를 클래스의 인스턴스로 변환하는데 사용된다.

class Person {
  String name;
  int age;

  Person(this.name, this.age);

  Person.fromMap(Map<String, dynamic> map) 
    : this.name = map['name'],
      this.age = map['age'];

  void introduce() {
    print('안녕하세요, 제 이름은 $name이고, 나이는 $age살입니다.');
  }
}

void main() {
  Map<String, dynamic> personMap = {'name': '홍길동', 'age': 25};
  Person person = Person.fromMap(personMap);
  person.introduce();
}

나머지 클래스 내용은 공식 문서 를 참고하자

비동기 처리 : Future/async/await

플러터에서 Future는 자바스크립트에서의 Promise라고 보면 된다.

import 'dart:math';

Future<int> getRandomNumber() async {
  var random = new Random();
  int num = await Future.delayed(Duration(seconds: 3), () => random.nextInt(100));
  print("got a number of $num");
  return num;
}

void main() async {
  print('Fetching random number...');
  int randomNumber = await getRandomNumber();
  print('Random number: $randomNumber');
}

함수 리턴에 Future를 적용하면 return값이 Future가 아니어도 자동 적용된다.
Future에 대한 비동기 처리는 async/await 구문을 적용해 처리한다.

stream

또 다른 비동기 처리 방식으로는 stream이 있다.
Future는 처리가 끝나면 알려주는 방식이고, Stream은 구독 방식이다.

Stream을 생성하고 관리하는 두 가지 방법이 있는데, async/yield 방식과 streamcontroller 방식이다.
async
와 yield는 Stream의 데이터를 자동으로 생성하고 관리하고 싶을 때 사용하고, StreamController는 Stream의 데이터를 수동으로 관리하고 싶을 때 사용한다.

Stream<int> countStream(int to) async* {
  for (int i = 1; i <= to; i++) {
    await Future.delayed(Duration(seconds: 1));
    yield i;  // 다음 값 발생
  }
}

void main() async {
  print('Start counting...');
  
  await for (int number in countStream(5)) {
    print(number);
  }

  print('Stream finished.');
}
import 'dart:async';

void main() {
  final controller = StreamController<int>();
  
  final streamListener = controller.stream.listen((val) {
    print('Received: $val');
  }); //listen하고 있다가 값을 전달 받으면 프린트

  for (int i = 1; i <= 5; i++) {
    controller.sink.add(i); // 값 stream에 전달
  }

  controller.close();
}

Future vs Stream

Future는 단일 값에 대한 비동기 작업을 나타낸다. Future는 하나의 값에 대한 결과가 준비되면 완료(complete) 상태가 되고, 그 값은 then이나 async/await를 통해 얻을 수 있다.

반면 Stream은 시간이 지남에 따라 여러 값을 생성할 수 있는 비동기 시퀀스다. Stream을 사용하면 시간이 지나면서 발생하는 이벤트를 처리하거나, 데이터를 순차적으로 처리할 수 있다. Stream은 시간에 따른 결과들을 리턴(yield)하고, 각 결과는 개별적인 Future로 처리된다.

Future는 한 번의 작업에 대한 완료를 기다리는 데 적합하며, Stream은 시간이 지남에 따라 발생하는 여러 이벤트를 처리하는 데 적합하다.

profile
의지와 행동

0개의 댓글