diff --git "a/hong/flutter/\354\275\224\353\223\234\355\214\251\353\217\204\353\246\254\354\235\230 \355\224\214\353\237\254\355\204\260 \355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/ch01.md" "b/hong/flutter/\354\275\224\353\223\234\355\214\251\353\217\204\353\246\254\354\235\230 \355\224\214\353\237\254\355\204\260 \355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/ch01.md" index a96e700..8dc4336 100644 --- "a/hong/flutter/\354\275\224\353\223\234\355\214\251\353\217\204\353\246\254\354\235\230 \355\224\214\353\237\254\355\204\260 \355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/ch01.md" +++ "b/hong/flutter/\354\275\224\353\223\234\355\214\251\353\217\204\353\246\254\354\235\230 \355\224\214\353\237\254\355\204\260 \355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/ch01.md" @@ -360,4 +360,171 @@ bool result = 12 > 10 && 1 > 0; // true bool result2 = 12 > 13 || 1 > 0; // true ``` -### +### 1.6. 제어문 + +제어문으로는 if, switch, for, while을 사용할 수 있다. + +사용 방식은 다른 언어와 같음. + +### 1.7. 함수와 람다 + +함수의 일반적인 특징 + +- 다트 함수에서 매개변수를 지정하는 방법으로 순서가 고정된 매개변수(positional parameter, 위치 기반 매개변수)와 이름이 있는 매개변수(named parameter, 명명된 매개변수)가 있음. +- named parameter를 지정하려면 중괄호 { } 와 required 키워드를 사용해야 함. + +```dart +int addTwoNumbers({ + required int a, + required int b, +}) { + return a + b; +} + +void main() { + print(addTwoNumbers(a: 1, b: 2)); +} +``` + +- required 키워드는 매개변수가 null 값이 불가능한 타입이면 기본값을 지정해주거나 필수로 입력해야 한다는 의미. +- 기본값을 갖는 positional parameter는 [ ] 기호를 사용함. + +```dart +int addTwoNumbers(int a, [int b = 2]) { + return a + b; +} + +void main() { + print(addTwoNumbers(1)); +} +``` + +- 입력값이 하나뿐이라서 두 번째 매개변수에 기본값 2를 적용해 계산한 결과를 반환함. + +```dart +// named parameter에 기본값 적용 +int addTwoNumbers({ + required int a, + int b = 2, // required 키워드를 생략하고 값 입력 +}) { + return a + b; +} + +// positional & named parameter 섞어 사용 +int addThreeNumbers( + int a, { + required int b, + int c = 4, +}) { + return a + b + c; +} + +void main() { + print(addTwoNumbers(a: 1)); + print(addThreeNumbers(1, b: 3, c: 7)); +} +``` + +익명 함수와 람다 함수 + +- 익명 함수(anonymous function)와 람다 함수(lambda function)은 함수 이름이 없고, 일회성으로 사용됨. +- 통상적으로 익명 함수와 람다 함수를 구분하지만 다트에서는 구분하지 않음. +- 익명함수와 람다 함수 표현 방식 + +```dart +// 익명 함수 +(매개변수) { + 함수 로직 +} + +// 람다 함수 +(매개변수) => 단 하나의 statement +``` + +- 익명 함수에 { } 를 빼고 ⇒ 기호를 추가한 것이 람다 함수 +- 매개변수는 아예 없거나 하나 이상이어도 됨. +- 코드 블록을 묶는 { } 가 없는 람다는 함수 로직을 수행하는 statement가 딱 하나인 경우만 사용 가능. +- 람다 함수는 이름을 정하고 미리 선언할 필요가 없어서 global scope로 다룰 필요가 없고, statement가 하나이기 때문에 적절히 사용하면 간결하게 코드를 작성할 수 있어서 가독성이 좋음 (실행하는 위치에 로직 코드가 있기 때문에) +- 때문에 콜백 함수나 list의 map(), reduce(), fold() 함수등에서 일회성이 높은 로직을 작성할 때 주로 사용함. +- 익명 함수 예시: + +```dart +void main() { + List numbers = [1, 2, 3, 4, 5]; + + // 일반 함수로 모든 값 더하기 + final allMembers1 = numbers.reduce((value, element) { + return value + element; + }); + print(allMembers1); + + // 람다 함수로 모든 값 더하기 + final allMembers2 = numbers.reduce((value, element) => value + element); + print(allMembers2) +} +``` + +typedef와 함수 + +- typedef 키워드는 함수의 시그니처를 정의하는 값으로 보면 됨. +- 여기서 시그니처는 반환값 타입, 매개변수 개수와 타입 등을 말함. +- 즉 함수 선어부를 정의하는 키워드 + +```dart +typedef Operation = void Function(int x, int y); + +void add(int x, int y) { + print(`결과값 : ${x + y}`); +} + +void substract(int x, int y) { + print(`결과값 : ${x - y}`); +} + +void main() { + // typedef는 일반적인 변수의 type처럼 사용 가능 + Operation oper = add; + + oper(1, 2); // 결과값 : 3 + + oper = substract; + oper(1, 2); // 결과값 : -1 +} +``` + +- 다트에서 함수는 일급 객체(first-class citizen)이므로 함수를 값처럼 사용할 수 있음. +- 그래서 flutter에서는 typedef으로 선언한 함수를 다음과 같이 매개변수로 넣어 사용함. + +```dart +typedef Operation = void Function(int x, int y); + +void add(int x, int y) { + print(`결과값 : ${x + y}`); +} + +void calculate(int x, int y, Operation oper) { + oper(x, y); +} + +void main() { + calculate(1, 2, add); // 결과값 : 3 +} +``` + +### 1.8. try … catch + +- 다른 언어와 사용 방식 같음. + +```dart +void main() { + try{ + final String name = 'roo'; + + throw Exception('wrong name'); + + print(name); + }catch(e){ + print(e); // Exception: wrong name + } +} +``` diff --git "a/hong/flutter/\354\275\224\353\223\234\355\214\251\353\217\204\353\246\254\354\235\230 \355\224\214\353\237\254\355\204\260 \355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/ch02.md" "b/hong/flutter/\354\275\224\353\223\234\355\214\251\353\217\204\353\246\254\354\235\230 \355\224\214\353\237\254\355\204\260 \355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/ch02.md" new file mode 100644 index 0000000..47fb853 --- /dev/null +++ "b/hong/flutter/\354\275\224\353\223\234\355\214\251\353\217\204\353\246\254\354\235\230 \355\224\214\353\237\254\355\204\260 \355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/ch02.md" @@ -0,0 +1,337 @@ +# 02. 다트 객체지향 프로그래밍 + +- 다트 언어는 높은 완성도로 객체지향 프로그래밍을 지원함. +- 플러터 역시 객체지향 프로그래밍 중심으로 설계된 프레임워크. + +### 2.1. 객체지향 프로그래밍의 필요성 + +- Map을 사용하면 단순히 값을 저장하는 것 외에 추가적인 편의기능을 구현할 수 없음. +- 클래스를 만들어 사용하면 필요한 값들만 입력하도록 제한하고 클래스에 특화된 하뭇들을 선언할 수 있음. +- 클래스는 일종의 설계또로서 데이터가 보유할 속성과 기능을 정의하는 자료구조. +- 클래스가 설계도, 인스터스화가 실물(실제 사용할 수 있는 데이터 생성). + +### 2.2. 클래스 + +- 객체지향 프로그래밍의 기본 = 클래스(class) +- 예제: + +```dart +class Idol { + String name = 'BANDIBOODI'; // 종속된 변수 = 멤버 변수, + + void sayName() { // 종속된 함수 = 메서드 + // 스코프 안에 값은 속성 이름이 하나만 존재한다면 this 생략 가능. + print('저는 ${this.name}입니다.'); + } +} + +void main() { + Idol bandiboodi = Idol(); + bandiboodi.sayName(); // 저는 BANDIBOODI입니다. +} +``` + +- 함수는 메서드를 포함하는 더 큰 개념임. +- 클래스에 정의된 함수인 메서드는 클래스의 기능을 정의한 함수 + +생성자 + +- constructor = 클래스의 인스턴스를 생성하는 메서드. + +```dart +class Idol { + final String name; + + Idol(String name) : this.name = name; +} + +// 생성자의 매개변수를 변수에 저장하는 과정을 생략할 수도 있음. +class Idol2 { + final String name; + + // this를 사용할 경우, 해당되는 변수에 자동으로 매개변수가 저장됨. + Idol(this.name); +} +``` + +- 생성자에서 입력받을 변수는 일반적으로 final로 선언함 (인스턴스화한 다음에 변수의 값을 변경하지 못하도록 하기 위해.) + +네임드 생성자 + +- named constructor = named parameter와 비슷한 개념. +- 일반적으로 클래스를 생성하는 여러 방법을 명시하고 싶을 때 사용. + +```dart +class Idol { + final String name; + final int membersCount; + + Idol(String name, int membersCount) + : this.name = name, + this.membersCount = membersCount' + + // 네임드 생성자 + Idol.fromMap(Map map) + : this.name = map['name'], + this.membersCount = map['membersCount']; +} +``` + +프라이빗 변수 + +- 다트에서의 private variable은 다른 언어와 정의가 조금 다름. +- 일반적으로 private variable은 class 내부에서만 사용하는 변수를 칭하지만, 다트 언어에서는 **같은 파일에서만 접근 가능한 변수임.** + +```dart +class Idol { + // _ 로 변수명을 시작하면 private variable을 선언할 수 있음. + String _name; + + Idol(this._name); +} + +void main() { + Idol bandiboodi = Idol('BANDIBOODI'); + + // 같은 파일에서는 _name 변수에 접근할 수 있지만, + // 다른 파일에서는 _name 변수에 접근할 수 없음. + print(bandiboodi._name); // BANDIBOODI +} +``` + +Getter / Setter + +- 최근에는 객체지향 프로그래밍을 사용할 때 변수의 값에 불변성(immutable: 인스턴스화 후 변경할 수 없는)을 특성으로 사용하기 때문에 Setter는 거의 사용하지 않음. + +```dart +class Idol { + String _name = 'BANDIBOODI'; + + String get name { + return this._name; + } + + // Setter는 매개변수로 딱 하나의 변수를 받을 수 있음. + set name(String name) { + this._name = name; + } +} + +void main() { + Idol bandiboodi = Idol(); + + bandiboodi.name = 'test'; // setter 사용. + print(bandiboodi.name); // getter 사용. 결과값: test +} +``` + +### 2.3. 상속 + +- extends 키워드를 사용해 상속(inheritance)할 수 있음. +- 상속은 어떤 클래스의 기능을 다늘 클래스가 사용할 수 있게 하는 기법. + +```dart +class BoyGroup extends Idol { + // 상속받은 생성자 + BoyGroup( + String name, + int membersCount, + ) : super( + name, + memberCount, + ); + +} +``` + +- super는 상속한 부모 클래스를 지칭 +- 부모 클래스에 기본 생성자가 있기때문에 BoyGroup에서는 Idol 클래스의 생성자를 실행하는 구조. + +### 2.4. 오버라이드 + +- override = 부모 클래스 또는 interface에 정의된 메서드를 재정의할 때 사용됨. +- 다트에서는 override 키워드를 생략할 수 있기 때문에 override 키워드를 사용하지 않고도 메서드를 재정의할 수 있음. + +```dart +class GirlGroup extends Idol { + // 생성자의 매개변수로 직접 super 키워드를 사용할 수도 있음. + GirlGroup( + super.name, + super. membersCount, + ); + + @override + void sayName() { + print('저는 여자 아이돌 ${this.name}입니다.'); + } +} +``` + +- 한 클래스에 이름이 값은 메서드가 존재할 수 없기 때문에 부모 클래스나 인터페이스에 이미 존재하는 메서드명을 입력하면 override 키워드를 생략해도 메서드가 덮어써짐. +- 하지만 직접 명시하는 게 협업 및 유지보수에 유리함. + +### 2.5. 인터페이스 + +- 상속은 공유되는 기능을 이어받는 개념. +- interface = 공통으로 필요한 기능을 정의만 해두는 역할. +- 다트에는 interface를 지정하는 키워드가 따로 없음. +- 상속은 단하나의 클래스만 할 수 있지만 인터페이스는 적용 개수에 제한이 없음. + +```dart +class GirlGroup implements Idol { + final String name; + final int membersCount; + + GirlGroup( + this.name, + this.membersCount, + ); + + void sayName() { + // ... + } + + void sayMembersCount() { + // ... + } +} +``` + +- 반드시 재정의할 필요가 있는 기능을 정의하는 용도로 인터페이스 사용. 실수로 빼먹는 일을 방지. + +### 2.6. 믹스인 + +- mixin = 특정 클래스에 원하는 기능들만 골라 넣을 수 있는 기능. +- 특정 클래스를 지정해서 속성들을 정의할 수 있으며, 지정한 클래스를 상속하는 클래스에서도 사용할 수 있음. +- 한 개의 클래스에 여러 개의 믹스인을 적용할 수도 있음. + +```dart +mixin IdolSingMixin on Idol { + void sing() { + print('${this.name}가 노래르 부른다.'); + } +} + +// mixin을 적용할 때는 with 키워드 사용 +class BoyGroup extends Idol with IdolSingMixin { + BoyGroup( + super.name, + super.membersCount, + ); +} + +void main() { + BoyGroup bandi = BoyGroup('BANDI', 6); + + // 믹스인에 정의된 sing() 함수 사용 가능 + bandi.sing(); // BANDI가 노래를 부른다. +} +``` + +### 2.7. 추상 + +- abstract = 상속이나 인터페이스로 사용하는 데 필요한 속성만 정의하고 인스턴스화할 수 없도록 하는 기능. +- 클래스를 인터페이스화할 일이 없다면, 클래스를 추상 클래스로 선언해서 해당 클래스의 인스턴스화를 방지하고 메서드 정의를 자식 클래스에 위임하는 방식. +- 추상 크랠스는 추상 메서드를 선언. +- 추상 메서드는 함수의 반환 타입, 이름, 매개변수만 정의. + +```dart +abstract class Idol { + final String name; + final int membersCount; + + Idol(this.name, this.membersCount); + + void sayName(); + void sayMembersCount(); +} +``` + +### 2.8. 제네릭 + +- generic = 객체지향 프로그래밍에서 가장 아름다운(?) 기능. +- 제네릭은 클래스나 함수의 정의 → 클래스를 선언할 때 X, 인스턴스화하거나 실행할 때로 미룬다. +- 특정 변수의 타입을 하나의 타입으로 제한하고 싶지 않을 때 자주 사용. +- 예를 들어, 정수를 받는 함수, 문자열을 받는 함수를 각각 `setInt()`, `setString()` 처럼 따로 만들지 않아도, 제네릭을 사용해 `set()` 함수 하나로 여러 자료형을 입력받게 처리할 수 있음. +- Map, List, Set 등에서 사용한 `<>` 사이에 입력되는 값이 제네릭 문자임. + +```dart +// 인스턴스화할 때 입력받을 타입을 T로 정의함. +class Cache { + // data의 타입을 추후 입력될 T 타입으로 지정함. + final T data; + + Cache({ + required this.data, + }); +} + +void main() { + // T의 타입을 List로 입력함. + final cache = Cache>( + data: [1,2,3], + ); + + // 제네릭에 입력된 값을 통해 data 변수의 타입이 자동으로 유추됨. + print(cache.data.reduce((value, element) => value + element)); // 6 +} +``` + +- 일반적으로 개발자들이 사용하는 제네릭 문자들 + - T: 변수 타입 표현 + - E: 리스트 내부 요소들의 타입을 표현 + - K: 키를 표헌 + - V: 값을 표현 + +### 2.9. Static + +- static = 클래스의 인스턴스에 귀속되지 않고, 클래스 자체에 귀속됨. + +```dart +class Counter { + static int i = 0; + + Counter() { + print(i++); + } +} + +void main() { + Counter(); // 1 + Counter(); // 2 + Counter(); // 3 +} +``` + +- 정적 변수 i는 Counter class에 귀속되기 때문에 instance를 호출할 때마다 1 씩 증가됨. +- 따라서, static 키워드는 인스턴스끼리 공유해야하는 정보에 지정. + +### 2.10. cascade operator + +- cascade operator = 인스턴스에서 해당 인스턴스의 속성이나 맴버 함수를 연속해서 사용하는 기능. +- 사용 기호는 `..` , 장점은 더 간결한 코드 작성 가능. + +```dart +void main() { + // cascade operator를 사용하면 선선한 변수의 메서드를 연속으로 실행 가능. + Idol bandiboodi = Idol('BANDIBOODI', 13) + ..sayName() // 저는 BANDIBOODI입니다. + ..sayMembersCount(); // BANDIBOODI 멤버는 13명입니다. +} +``` + +### 핵심 요약: + +1. Class 키워드를 사용해서 클래스를 선언할 수 있음. +2. 클래스를 인스턴스화하면 클래스의 인스턴스를 변수로 지정할 수 있음. +3. 상속받으면 부모 클래스의 모든 속성을 물려받음. + 1. extends 키워드 사용 + 2. 하나의 자식 클래스는 하나의 부모 클래스만 상속 받을 수 있음. +4. Override는 이미 선언되어 있는 속성을 덮어쓰는 기능. +5. Interfac는 클래스의 필수 속성들을 정의하고 강제할 수 있는 기능. +6. Mixin은 상속처럼 모든 속성을 물려받지 않고 원하는 기능만 골라서 적용할 수 있음. + 1. with 키워드를 사용해서 믹스인을 적용 + 2. 하나의 클래스에 여러 개의 믹스인을 적용할 수 있음. +7. Generic은 변수 타입의 정의를 인스턴스화까지 미룰 수 있음. +8. Static은 클래스에 직접 귀속되는 속성. +9. Cascade 연산자는 인스턴스에서 해당 인스턴스의 속성이나 멤버 함수를 연속해서 호출할 때 사용. diff --git "a/hong/flutter/\354\275\224\353\223\234\355\214\251\353\217\204\353\246\254\354\235\230 \355\224\214\353\237\254\355\204\260 \355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/\355\225\231\354\212\265 \352\263\204\355\232\215.md" "b/hong/flutter/\354\275\224\353\223\234\355\214\251\353\217\204\353\246\254\354\235\230 \355\224\214\353\237\254\355\204\260 \355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/\355\225\231\354\212\265 \352\263\204\355\232\215.md" new file mode 100644 index 0000000..ee5bd4b --- /dev/null +++ "b/hong/flutter/\354\275\224\353\223\234\355\214\251\353\217\204\353\246\254\354\235\230 \355\224\214\353\237\254\355\204\260 \355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/\355\225\231\354\212\265 \352\263\204\355\232\215.md" @@ -0,0 +1,27 @@ +학습 계획 +- 총 24 Chapter. +- 10월부터는 개발 예정. + +- [x] 7/21: chapter 2 + +- [ ] 7/27, 28: 3, 4 + +- [ ] 8/3, 4: 5, 6 + +- [ ] 8/10, 11: 7, 8 + +- [ ] 8/15: 9 + +- [ ] 8/17, 18: 10, 11 + +- [ ] 8/24, 25: 12, 13 + +- [ ] 8/31, 9/1: 14, 15 + +- [ ] 9/7, 8: 16, 17 + +- [ ] 9/14, 15, 16, 17, 18: 18, 19, 20, 21, 22 + +- [ ] 9/21, 22: 23, 24 + +- [ ] 9/28, 29: 실제 프로젝트 준비