1. 변수
// 변수
void main() {
int n1 = 1;
double d1 = 10.1;
bool b1 = true;
String s1 = "홍길동";
print("n1: ${n1}");
print("d1: ${d1}");
print("b1: ${b1}");
print("s1: ${s1}");
print(d1.runtimeType);
}

2. 타입 추론
void main() {
// 타입 추론
var n1 = 1;
// n1 = "문자열";
n1 = 3;
print(n1);
print(n1.runtimeType);
// 다이나믹 (Object)
dynamic n2 = 1; // 타입 변경이 가능
n2 = "문자열";
print(n2.runtimeType);
}

3. 함수
void f1() {
print("f1 호출됨");
}
void f2(int n1, int n2) {
print("f2 호출됨 : ${n1 * n2}");
}
int f3(int n1, int n2) {
return n1 * n2;
}
void main() {
f1();
f2(5, 3);
int result = f3(8,4);
print("f3 result = ${result}");
}

4. Lambda
// Lambda Function
var f1 = () {
print("f1 호출됨");
};
var f2 = () => print("f2 호출됨");
var f3 = () => 1;
int f4() {
return 1;
}
void main() {
f1();
f2();
print("f3 호출됨 : ${f3()}");
print("f4 호출됨 : ${f4()}");
}

5. Null 처리 & 선택적 매개변수
Null 처리 (Sound Null Safety)
- Dart의 기본 타입(int, double, bool, String)은 null을 받을 수 없음
- null을 처리하기 위해 ‘?’, ‘??’, ‘!’ 사용
- ? : 값이 있을 수도 있고, 없을 수도 있음 (Optional.ofNullable)
- Null Safety(Aware) Operator (Null 인지 연산자)
- ?? : 값이 있으면 그대로 주고, 없으면 다른 값 주기 (Optional.orElseGet)
- Null Coalescing Operator (Null 병합 연산자)
- ! : 값이 무조건 있음 (Optional.of)
- Null Assertion Operator (Null 부정 연산자)
선택적 매개변수 (Optional Parameters)
- Dart는 함수의 오버로딩을 지원하지 않음
- 대신, 매개변수를 선택적으로 넣을 수 있는 선택적 매개변수를 지원
- 선택적 매개변수를 추가하면 값이 null 또는 매개변수 값으로 들어감
- 이때, 값이 null일 경우 default 값도 설정 가능함
- 함수 호출 시 Key 값을 통해 값을 넣을 수 있음, 또는 넣지 않아도 됨
- 선택적 매개변수에서 값을 무조건 넣어야 할 경우?
- 선택적 매개변수에서 해당 매개변수를 제외
- 선택적 매개변수에서 해당 매개변수에 ‘required’ 추가
- 이 경우 키 값을 통해 값을 넣을 수 있어 편리하지만 코드가 길어질 수 있음
// null 처리, 선택적 매개변수
String? username = "nulla";
// s1은 ? 타입, s2는 선택적 매개변수로 인한 default 값 설정
int lenDiv({String? s1, String s2 = "hello"}) {
return (((s1 ?? "ssar").length + s2.length) / 2).toInt();
}
void main() {
int? len = username?.length; // Optional.ofNullable (null 허용)
print(len);
int len2 = username!.length; // Optional.of (null이면 터짐)
print(len2);
int len3 = (username ?? "ssar").length; // Optional.orElseGet (null이면 다른값)
print(len3);
int len4 = lenDiv(s1: username);
print(len4);
}


6. 클래스
- 클래스 기본
// 클래스
class User {
String username;
String password;
User(this.username, this.password);
}
void main() {
User u1 = User("ssar", "1234");
print(u1.username);
print(u1.password);
}
- 선택적 매개변수 활용
// 클래스
class User {
String username;
String password;
User({required this.username, this.password = "1234"});
}
void main() {
User u1 = User(username: "ssar");
print(u1.username);
print(u1.password);
}
- Initialized Keyword (:) 사용
// 클래스
class User {
String username;
String password;
User(String username, String password)
: this.username = username,
this.password = password == "1234" ? "5678" : password;
}
void main() {
User u1 = User("ssar", "1234");
print(u1.username);
print(u1.password);
}
- 초기화 함수 init & cascade 사용
// 클래스
class User {
String username;
String password;
User(this.username, this.password);
void init() {
if (username == "ssar") {
if (password == "1234") {
this.password = "9999";
}
}
}
}
void hello(User u) {}
void main() {
hello(User("ssar", "1234")..init());
}
- 이름이 있는 생성자
- 기본 생성자와는 다른 상태를 부여할 수 있음
class Button {
String text;
String color;
int x;
int y;
int width;
int height;
Button(
this.text, {
this.color = "회색",
this.x = 0,
this.y = 0,
this.width = 200,
this.height = 150,
});
Button.block(
this.text, {
this.color = "회색",
this.x = 0,
this.y = 0,
this.width = 100000000,
this.height = 150,
});
static Button inlineButton(String text) {
return Button(text);
}
}
void main() {
Button basicButton = Button("로그인");
Button redButton = Button("로그인", color: "red");
Button blockButton = Button.block("회원가입");
Button inlineButton = Button.inlineButton("회원가입");
}
7. 상속 & 컴퍼지션
상속 (Inherit)
- 한 클래스가 부모의 클래스를 상속받아 자신의 클래스이면서 부모 클래스의 성질도 가질 수 있음
- 상속은 하나의 클래스밖에 받을 수 없음
// 상속
class Burger {
String name;
Burger(this.name);
}
// is
class ChickenBurger extends Burger {
int price;
ChickenBurger(this.price, super.name);
}
class CheeseBurger extends Burger {
CheeseBurger(String name) : super(name);
}
void main() {
Burger b1 = CheeseBurger("치즈버거");
Burger b2 = ChickenBurger(1000, "치킨버거");
}
Composition
- 상속 관계가 아닌, 의존성에 의한 연결 관계
- Dart에서는 mixin, with를 제공하여 편하게 사용 가능
- 한 번에 여러 클래스를 받을 수 있음
- 다른 클래스를 참조(.)하지 않고도 상태를 참조할 수 있음 → 내 클래스의 상태처럼 사용 가능
mixin class Engine {
int power = 5000;
}
mixin class Wheel {
int size = 21;
}
// has
class Car with Engine, Wheel {}
void main() {
Engine e = Engine();
Car c1 = Car();
print(c1.power);
print(c1.size);
}
Share article