Dart에는 var 타입과 dynamic 타입이 존재
var 타입에는 아무 자료형이나 넣을 수 있지만, 첫 자료형 타입으로 고정시켜 준다.
반면 dynamic 타입은 아무 자료형이나 막 바꿔서 넣어줄 수 있다.
var name = "jinhyeok";
name = 123;
이렇게 하면 컴파일 에러가 난다.
dynamic name = "jinhyeok";
name = 123;
이렇게 하면 괜찮다.
이 외 기본 자료형은
int, String, double, bool 등등이 있다.
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);
const는 build time에 값이 정해져 있어햐 한다.
반면 final은 run time에 값이 결정된다
void main() {
final now1 = new DateTime.now(); // 가능
const now2 = new DateTime.now(); // 불가능
}
for (int i = 0; i < 10 ; i++) // 첫번째 방법
List<int> items = [1, 2, 3, 4, 5];
for (item in items) // 두번째 방법
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
*/
var nav = ['Home', 'Furniture', 'Plants', if (promoActive) 'Outlet'];
var listOfInts = [1, 2, 3];
var listOfStrings = ['#0', for (var i in listOfInts) '#$i'];
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);
}
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);
}
참고로 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을 이용해 생성자 초기화 리스트를 정의하는 방법은 데이터베이스에서 읽은 데이터나 네트워크를 통해 받은 데이터를 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는 자바스크립트에서의 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이 있다.
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는 단일 값에 대한 비동기 작업을 나타낸다. Future는 하나의 값에 대한 결과가 준비되면 완료(complete) 상태가 되고, 그 값은 then이나 async/await를 통해 얻을 수 있다.
반면 Stream은 시간이 지남에 따라 여러 값을 생성할 수 있는 비동기 시퀀스다. Stream을 사용하면 시간이 지나면서 발생하는 이벤트를 처리하거나, 데이터를 순차적으로 처리할 수 있다. Stream은 시간에 따른 결과들을 리턴(yield)하고, 각 결과는 개별적인 Future로 처리된다.
Future는 한 번의 작업에 대한 완료를 기다리는 데 적합하며, Stream은 시간이 지남에 따라 발생하는 여러 이벤트를 처리하는 데 적합하다.