[Dart] 클래스(Class) 사용 방법

Dart에서 클래스(Class) 사용 방법에 대해 알아보겠습니다.

Class

클래스 안에서 property를 선언할 때는 타입을 사용해서 정의합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Player {
final String name = 'eden';
final int age = 3;

void sayName() {
print("Hi my name is $name");
}
}

void main() {
// new 를 꼭 붙이지 않아도 됩니다.
var player = Player();
player.sayName();
}

클래스 메서드 안에서는 this 를 붙이지 않는 것을 Dart에서는 권장하나, 어쩔 수 없이 같은 변수명이 있을 때는 this를 붙여서 사용해야 합니다.

Constructor

생성자(constructor) 함수는 클래스 이름과 같아야 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Player {
// late 사용
late final String name;
late final int age;

Player(String name, int age) {
this.name = name;
this.age = age;
}
}

void main() {
// Player 클래스의 인스턴스 생성
var player = Player("eden", 3);
}

위의 생성자 함수는 다음과 같이 줄일 수 있습니다.

1
2
3
4
5
6
7
class Player {
// late 사용 안함
final String name;
final int age;

Player(this.name, this.age);
}

위의 코드는 late 를 사용하였지만 아래 코드에서 사용하지 않은 이유는 생성자 함수를 만들 때 변수에 값을 할당하지 않았기 때문입니다.

이전 생성자 함수를 만들 때에는 this.name = name; 식으로 값을 할당했기 때문에 먼저 선언한 변수에 late 를 붙여야 오류가 발생하지 않습니다.

Named Constructor Parameters

클래스가 거대해질 경우 다음과 같이 생성자 함수를 만드는 것은 비효율적일 것입니다. 많은 파라미터를 받아야 하고 각 파라미터의 의미를 알 수가 없습니다.

1
2
3
4
5
6
7
8
9
10
11
12
class Team {
final String name;
int members;
int ranking;
String description;

Team(this.name, this.members, this.ranking, this.description);
}

void main() {
var team = Team("Tottenham", 25, 5, "Tottenham Hotspur Football Club");
}

문제를 해결하려면 너무 간단합니다. 생성자 함수 생성할 때 중괄호({})를 사용하는 것입니다. 그리고 클래스를 정의할 때 Named Paramaters를 사용합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Team {
final String name;
int members;
int ranking;
String description;

Team({this.name, this.members, this.ranking, this.description});
}

void main() {
var team = Team(
name: "Tottenham",
members: 25,
ranking: 5,
description: "Tottenham Hotspur Football Club");
}

하지만 여기에는 큰 문제가 있습니다. 변수가 null 일 수도 있기 때문에 기본 값(default value)을 주거나 required 파라미터 앞에 붙여 사용합니다. 다음의 코드는 required를 사용하였습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Team {
final String name;
int members;
int ranking;
String description;

Team({
required this.name,
required this.members,
required this.ranking,
required this.description
});
}

void main() {
var team = Team(
name: "Tottenham",
members: 25,
ranking: 5,
description: "Tottenham Hotspur Football Club");
}

Named Constructor

콜론(:)을 사용하면 특별한 생성자 함수를 만들 수 있습니다.
콜론을 넣음으로써 dart에게 객체를 초기화하라고 명령할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Team {
String name;
int members;
String description;

Team({required this.name, required this.members, required this.description});

Team.createTeam({required String name, required int members})
: this.name = name,
this.members = members,
this.description = "$name team is good.";
}

void main() {
var team = Team.createTeam(
name: "Tottenham",
members: 25,
);
}

Enum

Enum 은 우리가 코드를 작성할 때 실수를 하지 않게 도와줍니다.
enum type 의 변수들은 해당 enum type에 생성된 값들 중에서만 값이 할당될 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
enum Team { red, blue }

class Player {
String name;
Team team;

Player({required this.name, required this.team});
}

void main() {
var player = Player(name: 'eden', team: Team.red);
}

Abstract Class

추상 클래스는 다른 클래스들이 직접 구현해야 하는 필드와 메서드들을 모아놓은 클래스입니다.
추상 클래스는 아직 메소드와 내용이 추상적이므로 객체를 생성할 수 없습니다.
추상 클래스를 상속받는 클래스들은 추상 클래스의 메서드들을 구현해야 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
abstract class Person {
void walk();
}

class Player extends Person {
String name;
String team;

Player({required this.name, required this.team});

void walk() {
print("Player is walking");
}
}

void main() {
var player = Player(name: 'eden', team: 'red');
player.walk();
}

Mixin

Mixin은 생성자가 없는 클래스를 의미합니다.
Mixin은 클래스에 코드를 재사용하기 위해 사용되며, 다중 상속의 일부 단점을 보완합니다. Mixin은 extends가 아닌 with 키워드를 사용하여 클래스에 적용합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
mixin Strong {
final double strengthLevel = 100.5;
}

mixin Tall {
final double height = 180;
}

mixin QuickRunner {
void run() {
print("run!!");
}
}

class Player with Strong, Tall, QuickRunner {
final String name;

Player({required this.name});
}

void main() {
var player = Player(
name: "eden",
);
player.run(); // run!! 출력
}

상속과 Mixin 의 차이점

extends를 사용하여 상속받은 클래스는 자식 클래스, 상속한 클래스는 부모클래스가 되는 것이고, 자식 클래스는 부모 클래스를 super 를 통해서 접근할 수 있습니다.

Mixin with 라는 키워드를 통해서 단순히 Mixin 내부의 프로퍼티와 메서드들을 가져오는 것뿐입니다.

Share