1. class
- 상태와 행위
- 행위는 상태를 변화시킴
2. 함수와 메서드
- 클래스 안에 있으면 메서드
- 상태를 매개변수로 받지 않음
- 상태가 공유되는 것이 위험함 → 동기에 해서 사이트이팩트가 일어날 수 있음
싱크로나이즈드를 붙여서 동기화하기
상태값이 아닌 DB값을 변경하면 트랜잭션이 걸리게 하기
⇒ 순차적으로 실행하게 만들어야 함
클래스가 없는 함수형 프로그램을 사용하기도 함
- 상태가 있기에 결과가 누적됨
- 행위를 통해 상태가 변경됨
- 밖에 있으면 함수
- 매개변수와 결과 값이 나옴
- 상태가 없어서 결과가 누적되지 않음
- 결과 값만 도출
3. 불변성이 중요함!
- map을 사용하면 불변하기에 사이드 이펙트가 일어나지 않음
변경 불가능한 데이터 구조
해당 데이터 구조 자체가 변경되지 않고 새로운 map이 생성
이전 상태의 데이터를 보존하면서 새로운 데이터를 생성 가능
4. 깊은 복사와 얕은 복사
- 깊은 복사 (Deep Copy) : 새로 생성
- 객체를 완전히 복제하는 것
- 객체 내부에 있는 모든 요소들을 재귀적으로 복사하여 새로운 객체를 생성
- 원본 객체와 복제된 객체는 완전히 독립적 → 한 객체의 변경이 다른 객체에 영향을 주지 않음
- 복잡한 객체의 복사 시에 성능과 메모리 사용량이 높아질 수 있음
- 얕은 복사 (Shallow Copy) : 덮어씌워짐
- 객체를 복제할 때, 객체의 첫 번째 레벨의 요소만을 복제하는 것
- 객체 내부의 객체는 참조로 복사
- 객체 내부의 변경은 복제된 객체와 원본 객체에 모두 반영
- 복잡한 객체의 복사 시에는 원하지 않는 동작을 일으킬 수 있음
5. 객체 지향 프로그래밍
class Dog { String name = "Toto"; // 클래스 변수는 클래스가 떠야 heap에 뜸 int age = 13; String color = "white"; int thirsty = 100; } void main() { Dog d1 = Dog(); d1.thirsty = 50; print("갈증 지수는 ${d1.thirsty}"); }
6. 생성자
- 기본 생성자
class Dog { String name; int age; String color; int thirsty; // new가 될 때 기본값이 0 Dog(this.name, this.age, this.color, this.thirsty) {} } void main() { Dog d1 = Dog("토토", 0, "흰색", 100); Dog d2 = Dog("망고", 2, "흰색", 50); print("d1의 이름은 ${d1.name}"); print("d2의 이름은 ${d2.name}"); }
- 기본 생성자와 같으나 값을 설정해서 생성 가능
class Dog { String name; // new될때 받기 int age; // 기본값 0 String color; // new될때 받기 int thirsty; // 기본값 0 // Dog(this.name, this.age, this.color, this.thirsty); Dog(String name, int age, String color, int thirsty) : this.name = name, this.age = age, this.color = color, this.thirsty = thirsty; } void main(){ Dog d1 = Dog("토토", 0, "하얀색", 0); }
7. 선택적 매개변수
- 생성된 순서대로 안넣어도 됨
- 키 값이 있어 가독성이 좋음
class Dog { String name; // new될때 받기 int age; // 기본값 0 String color; // new될때 받기 int? thirsty; // 기본값 0 Dog.logic(this.name, this.age, this.color, this.thirsty) { age = age + 10; print("logic 실행됨"); } Dog.select( {required this.name, this.age = 0, required this.color, this.thirsty}); Dog(this.name, this.age, this.color, this.thirsty); Dog.copy(Dog oldDog) : this.name = oldDog.name, this.age = oldDog.age, this.color = oldDog.color, this.thirsty = oldDog.thirsty; } void main() { Dog d4 = Dog.select(name: "토토", color: "빨간색", age: 10); print(d4.name); print(d4.color); print(d4.age); print(d4.thirsty); // Dog d1 = Dog("토토", 0, "하얀색", 0); // Dog d2 = d1; // Dog d3 = Dog.copy(d1); // print(d1.hashCode); // print(d2.hashCode); // print(d3.hashCode); }
- 오버로딩을 지원하지 않음
- 필요없는 인수는 전달하지 않아도 됨
class User { int? id; // DB에는 있지만 들어가기 전에 NULL일 경우 String username; String password; String? profileUrl; User( {this.id, required this.username, required this.password, this.profileUrl}); User.toEntity(UserDTO.user) : this.username = user.username; this.password = user.password; } void main() { User u1 = User(username: "ssar", password: "1234"); }
void main() { String username = "ssar"; print(username.length); }
void main() { String? username; // null일 수도 아닐 수도 있을 때 print(username?.length); // null일 때 분기 처리 방법 }
void main() { String? username = "ssar"; // null일 수도 아닐 수도 있을 때 print(username?.length); // null일 때 분기 처리 방법 }
void main() { String? username; // null일 수도 아닐 수도 있을 때 print(username?.contains("s")); // null일 때 분기 처리 방법 }
8. Cascade 연산자
class Chef { String name; Chef(this.name); void cook() { print("요리를 시작합니다"); } } void main() { Chef c1 = Chef("홍길동")..cook(); // cascade 연산자 print("요리사 이름 ${c1.name}"); }
9. Null 연산자
- ? : null 체크 연산자
- ?? : null 대체 연산자
- ! : null 강제 연산자
.get // 무조건 있으니까 가져와
void main() { String? username; // null일 수도 아닐 수도 있을 때 print(username!.length); }
10. late 연산자
- 초기화를 미룰 수 있음
- 타이밍의 문제
class JoinDTO { String username; String password; late String email; JoinDTO({required this.username, required this.password}); } void main() { JoinDTO dto = JoinDTO(username: "ssar", password: "1324"); dto.email = "ssar@nate.com"; // 타이밍이 늦어도 받긴 받음 }
Share article