====== dart 언어 ====== https://dartpad.dev/ ===== 일반 ===== void main() { for (int i = 0; i < 5; i++) { print('hello ${i + 1}'); } // type String, double, int, bool, var print ( name + ' ' + name2); print ('$name $name2'); // 변수만 쓰면 {} 없어도 됨 print ('${number+1} ${name2}'); // var, dynamic print (name.runtimeType); //var : 한번 선언하면 fix // dynamic : type 바뀔 수 있음 // nullable, non-nullable String? name = 'asd'; // ? 끝에 붙이면 name = null; //가능 print(name2!); // !현재 이값은 null이 아니다 (null 안들어가는 함수쓸 때) final String name = 'asdf'; // name 바꿀 수 없음 const String name2 = 'asdf'; // 비슷 final name = 'sdaf'; // type 생략 가능 const name2 = 'sadf'; // type 생략 가능 // 차이 // final : build time final DateTime now = DateTime.now(); //build time 몰라도 됨 // const 는 안됨 : build time 알고 있어야 함 (절대적으로) // % : 나머지 number ++; // +1 하면서 변경 ex. --; number += 2; // +2 하면서 변경 ex. *=, /= number ??= 3; // number가 null이면 3 (아니면 안바뀜) // == 같은지, != 다른지 // type비교 print (number1 is int); print (number1 is! String); bool result = 12 > 10 && 1 > 0; // || : or // List List lst = ['1','2','3']; // List numbers = [1,2,3]; lst[0]; lst.length; lst.add('4'); lst.remove('3'); lst.indexOf('4'); // Map : Key/Value Map dictionary = { 'a' : '1', 'b' : '2', }; dictionary.addAll( { ~~~ } ); dictionary['a']; dictionary['c'] = '3'; dictionary['c'] = '4'; //변경 dictionary.remove('a'); dictionary.keys; dictionary.values; // Set : 중복없는 list final Set names = { 'a','b','c', 'c' }; names.add('d'); names.remove('a'); names.contains('d'); if (조건) { } else if ( 조건 ) { } else { } switch ( number % 3 ) { case 0: print('sadf'); break; //넣어줘야 함 case 1: ... default: print('sdf'); break; } for ( int i = 0; i < 10; i++) { } for ( int number in numbers ) { } // numbers list에 있는 값들 while ( 조건 ) { } do { } while ( ); //먼저 do 하고 (거의 안씀) // break; // continue; } // enum : 함수 밖에 선언 enum Status { approved, pending, rejected, } // 함수 밖에 선언 //사용할 때 Status status = Status.pending; if (status == Status.approved ) { .... } // 정확히 이 세개 밖에 없다는 것을 알려줌, 오타 방지 /////////////////////////////////////////////////////////////////////////////////////// //// 함수 /////////////////////////////////////////////////////////////////////////////////////// // positional parameter addNumbers(int x, [int y=20, int z=30]) { } // [ Optional ], null이 된다면 [int? y, int? z] // 없으면 void와 동일 // named parameter addNumbers({ required int x, required int y, required int z } ) { } // addNumbers(y:10, x:20, z:30 ) // 순서 바뀌고 이름 넣어야 함 addNumbers({ required int x, required int y, int z=30 } ) { } // required 없애면 optional이 됨 int addNumbers ( ) { return x; } // arrow function int addNumbers( int x, {required int y, int z = 30,} ) => x+y+z; // typedef : 함수 밖에 선언 typedef Operation = int Function(int x, int y, int z); // int add(int x, int y, int z) => x+y+z; int substract(int x, int y, int z) => x-y-z; // 사용할 때1 Operation operation = add; // add라는 함수로 정의 int result = operation(10,20,30); // 사용할 때2 int calculate(int x, int y, int z, Operation operation) { return operation(x,y,z); }} int result2 = calculate(30,40,50,add); /////////////////////////////////////////////////////////////////////////////////////// //// CLASS /////////////////////////////////////////////////////////////////////////////////////// void main() { //Idol blackpink = Idol(); // new Idol(); 같음 //Idol blackpink = Idol('블랙핑크', ['a','b','c']); // new Idol(); 같음 print(blackpink.name); blackpink.sayhello(); } // Idol class class Idol { // _Idol (constructor 이름도 바꿔주면) : private 속성 : 다른파일에서 import 해도 못씀 final String name; final List members; // 웬만하면 final 로 선언해야 함 : immutable programming // CONSTRUCTOR 사용법 // 1. constructor Idol(String name, List members) : this.name = name; this.members = members; // 2. // Idol(this.name, this.members); //로 하면 더 간단함 // const Idol(this.name, this.members); 로 하면 좋음? //const constructor : (변수들이 final일 때) // -> 사용할 때 Idol blackpink = const Idol('A', ['a'] ); // Idol blankpink2 = const Idol('A', ['a'] ); // 일 때,(똑같은 변수) const 이면 blackpink == blankpink2 는 true, 아니면 false // 3. named constructor Idol.fromList(List values) : this.members = values[0], this.name = values[1]; // 1or2 와 공존 가능하고, // instance 선언할 때 // Idol bts = Idol.fromList ( [ ['a','b','c'], 'BTS' ] ); // 로 사용 가능 void sayHello() { print('안녕하세요 ${this.name} 입니다.'); // method 안에 name 없으면 this. 없어도 됨 } void introduce() { print('저희 멤버는 ${this.members}가 있습니다'); } // getter String get firstMember { // () 없음 return this.members[0]; } // 사용 : blackpink.firstMember // setter set firstMember(String name) { //무조건 한개 parameter this.members[0] = name; } // final, const 없어야 함 // 사용 : blackpink.firstMember = '아이언맨' // final (immutable programming) 때문에 setter는 잘 안씀 //static은 instance에 귀속되지 않고, class에 귀속된다 static String? building; // Idol.building = '하이브타워'; // 클래스에 direct로, instance끼리 공통 static void printBuilding() { } // static method } // 상속 (inheritace) // BoyGroup은 Idol type 도 됨 : is Idol = true class BoyGroup extends Idol { //extends BoyGroup ( String name, int membersCount, ) : super(name : name, membersCount : membersCount); //constructor : super void sayMale() { print("나는 남자"); } // method - class 내부에 있는 함수 // override @override // @override 써주면 직관적임 (없어도 됨) void method_of_parent() { return super.method_of_parent() ~~~; //super 부모 method 그대로 가져오기 } } // interface : 클래스에 필수적인 template abstract class Idolinterface() { //abstract : instance로 만들 수 없음 (설계로만 쓸거임) String name; IdolInterface(this.name); void sayName() {} } class BoyGorup implements Idolinterface{ //인터페이스와 동일한 구조로 만들어야 함 } // generic : 타입을 변수처럼 외부에서 받을 때 // ex. List : List를 String으로 class Lecture { // 여러개 넣을 수 있음 final T id; final String name; Lecture(this.id, this.name); } // Lecture lec1 = Lecture('123','lec1'); // OOP : 모든 클래스는 extends Objects() 하고 있음 /////////////////////////////////////////////////////////////////////// //Functional Programming : (중요 : 새로운 객체로 나옴!) /////////////////////////////////////////////////////////////////////// // 코드 간결 // 형변환 List b = ['a',...,'d']; b.asMap(); b.toSet(); Map c = b.asMap(); c.keys; // () : Iterable<> -> List로 바꿔줘야 함 c.keys.toList(); // map : 새로운 list가 나옴 ( b == new_b : false ) final new_b = b.map((x) { // list의 각각 원소가 x로 들어감 return '블랙핑크 $x'; } ); new_b.toList(); //Iterable 로 나오니까 //arrow 로 간편하게 final new_b2 = b.map( (x) => '블랙핑크 $x' ); // map 예시 String number = '13579'; final parsed = number.split('').map( (x) => '$x.jpg').toList(); // [1.jpg, 2.jpg, ...] //MAP 형인 경우 final result = new_b.map( (key,value) => MapEntry( 'asdf $key', '123 $value',) ); final keys = new_b.keys.map( (x) => 'sdf $x').toList(); //Set형 인경우 newSet = b.map( (x) => ... ).toSet(); // Where List< Map > people = [ {'name': ~~, 'group': '~~~'}, {~~~} ]; // List 안에 Map final blackpink_p = people.where( (x) => x['group'] == '블랙핑크' ).toList(); //맞는것만 남김 //Reduce List numbers = [1,3,5,7,9]; final result = numbers.reduce( (prev,next) { print('----'); print('prev : $prev'); print('next : $next'); return prev+next; } ); //(1+3) -> 4 // + 5 -> 9 // + 7 = 16... final result = numbers.reduce( (prev,next) => prev + next ); List words = ['a','b','c']; final sentence = words.reduce( (prev,next) => prev + next ); //Fold : return이 같은 형이 아니어도 됨 final sum = numbers.fold( 0, (prev,next) => prev + next ); // 0 + 1 = 1 // + 3 final sentence = words.fold( '', (prev,next) => prev + next ); final count = words.fold( 0, (prev,next) => prev + next.length ); //글자들의 길이 // cascading operator List even = [2,4,6,8]; List odd = [1,3,5,7]; print( [...even, ...odd]); // ... 하면 List 없어지고, 원소들이 나옴 (원래는 [[...], [...]] ) // 예시 // 원래 Map은 name, group 말고 다른 이름이든 다른 추가 내용이든 있을 수 있음 (자유도 높음) // Json 등으로 들어온 데이터를 class 로 유효성 검사? List< Map > people = [ {'name': ~~, 'group': '~~~'}, {~~~} ]; // List 안에 Map final parsedPeople = people.map ( (x) => Person ( name: x['name']!, group: x['group']!, ) ).toList(); // !로 무조건 존재한다 표현 print(parsedPeople); // toString override한 걸로 string 으로 바뀌어서 출력됨 (원래는 'instance of Person' 으로 출력됨 ) // 아래 처럼 data 유효성 검사 없이 활용 가능함 for (Person person in parsedPeople) { print(person.name); print(person.group); } final bts = parsedPeople.where( (x) => x.group == 'BTS'); class Person { final String name; final String group; Person( { required this.name, required this.group, } ); @override String toString() { return 'Person(name:$name, group:$group)'; } } /////////////////////////////////////////////////////////////////////// ////Asynchronous Programming /////////////////////////////////////////////////////////////////////// // CPU Thread : 실행 단위 (실행 중에는 사용 불가) // 서버요청 예시 : Network 요청을 위해서 돌아올 때까지 CPU가 막혀버림 (사용하지 않음에도) : synchronous programming // CPU 효율적으로 사용하는 방법 //Future //Future name = Future.value('코드팩토리'); //미래에서 받아올 값 // delayed - 2개의 파라미터 : 지연할 기간 Duration, 지연 지난 후 실행할 함수 Future.delayed( Duration(seconds: 2), () { print('Delay 끝'); } ); //예시 void addNum(int n1, int n2) { print (' 시작 ' ); //서버시뮬레이션 Future.delayed( Duration(seconds:2), () { print(' 계산완료'); }); print ('함수완료'); } addNum(1,1); //실행하면 : 시작->함수완료->계산완료 (Future 없으면 시작->계산완료->함수완료) //CPU 쉬고 있는 순간 다른 것 먼저 실행 //await : 실제로 논리적으로 기다리긴 함 //함수완료에서 await 결과가 필요할 때 void addNum(int n1, int n2) async { //async 필요함 print (' 시작 ' ); //서버시뮬레이션 await Future.delayed( Duration(seconds:2), () { //await print(' 계산완료'); }); print ('함수완료'); } //하지만 CPU는 다른 작업하기는 함 addNum(1,1); addNum(2,2); // 계산시작(1,1) - 계산시작(2,2) - (계산완료 - 함수완료)(1,1) - (계산완료 - 함수완료)(2,2) // 1,1 2,2 순서대로 하고 싶을 때 void main() async{ await addNum(1,1); await addNum(2,2); } //await은 Futre가 return되는 것만 됨 Future addNum(....) { } // 받아서 사용 void main() async{ Future result1 = await addNum(1,1); Future result2 = await addNum(2,2); print( result1+result2); } //Stream // Futre : 실행 -(await)->완료-반환 (1개) // Stream : 실행 -(yield-반환값1)-(yield-반환값2) -... -> 완료 import 'dart:async'; // 잘 안씀 : open src pkg 가 있으니까 이런 raw lib 쓸일은 없음 final controller = StreamController(); final stream = controller.stream.asBroadcastStream(); //as~ : 2번이상 listener하려면 필요 //1은 짝수만, 2는 홀수만 final streamListener1 = stream.where( (val) => val % 2 == 0).listen( (val) { print('Listener 1: $val'); }); final streamListener2 = stream.where( (val) => val % 2 == 1).listen( (val) { print('Listener 2: $val'); }); controller.sink.add(1); controller.sink.add(2); controller.sink.add(3); controller.sink.add(4); controller.sink.add(5); // 예시 void main(){ // 1초씩 동시에 실행됨 cal(2).listen( (val) { print (' $val'); }); cal(4).listen( (val) { print (' $val'); }); } Stream cal(int num) async* { for (int i=0; i<5; i++ ) { //return i*num; //return 이면 0만 return 되고 끝나버림 yield i*num; //cal 함수를 listening하는 stream에 값을 뿌려줄 수 있음 await Future.delayed( Duration(seconds: 1)); // 1초씩 계산되어 나옴 } } // 순서대로 실행 playAllStream.listen( (val) { print(val); }); Stream playAllStream() async* { yield* cal(1); // * : 모든 값이 나올 때까지 기다림 yield* cal(1000); } ===== 날짜, Duration ==== DateTime now = DateTime.now(); now now.year now.month now.day now.hour now.minute now.second now.millisecond Duration duration = Duration(seconds: 60); duration duration.inDays duration.inHours duration.inMinutes duration.inSeconds duration.inMilliseconds DateTime sepcificDay = DateTime( 2023,11,23, //위 순서대로 ); final diff = now.difference(specificDay); diff.inDays // .... now.isAfter(specificDay) now.isBefore(specificDay) now.add(Duration(hours:10)) now.substract(Duration(seconds:20)) {{tag>sotfware_development dart language}} ~~DISCUSSION~~