Dart는 객체 지향 프로그래밍 언어로, 클래스와 객체 지향 프로그래밍 개념을 지원한다.
클래스는 객체를 생성하기 위한 청사진, 객체는 클래스의 인스턴스이다.
Dart에서 클래스를 정의하는 법은 다음과 같다.
class 클래스명 {
// 멤버 변수(field) 정의
// 생성자(constructor) 정의
// 메소드(method) 정의
}
: 클래스 내부에 정의된 변수
해당 클래스의 인스턴스(객체)가 가지는 데이터로, 다른 객체와 데이터를 공유하지 않고 각 객체가 고유한 값을 갖는다. 초기값을 가질 수 있다.
class Player {
String name = '지은'; // 멤버 변수
int age = 27; // 멤버 변수
}
void main() {
var player1 = Player();
print(player1.name); // 지은
}
: 클래스 내부에 정의된 함수
Dart에서this
키워드는 현재 객체(인스턴스)를 가리키는 데 사용하며, this
를 사용하여 현재 객체의 멤버 변수나 메소드에 접근할 수 있다. this
는 생략할 수 있다.
class Player {
final String name = '지은';
int age = 27;
void sayHello() { // 메소드
print('Hello, my name is $name');
}
}
void main() {
var player1 = Player();
player1.sayHello(); // Hello, my name is 지은
}
클래스가 객체를 생성할 때 초기화할 때 사용되며, 주어진 데이터를 클래스의 멤버 변수에 할당하는 역할을 한다.
클래스 생성자를 정의하는 방법은 아래와 같다.
class 클래스명 {
// 멤버 변수 정의
// 생성자 정의
클래스명(파라미터1, 파라미터2...) {
// 생성자에서 멤버 변수 초기화
}
}
아래의 코드에서 Player
클래스는 name
과 age
라는 멤버 변수를 가지고 있으며, 생성자는 파라미터를 받아와 멤버 변수에 할당한다.
class Player {
late final String name;
late int age; // late 키워드는 값을 나중에 받아오는 것을 허용
Player(String name, int age) { // 생성자
this.name = name;
this.age = age;
}
}
void main() {
var player1 = Player('지은', 27);
print(player1.name); // 지은
var player2 = Player('지지', 13);
print(player2.name); // 지지
}
생성자 파라미터는 두 가지 방식으로 정의할 수 있다.
: 생성자 호출 시 매개변수의 위치(순서)를 기준으로 값을 전달하는 방법
Positional parameters를 사용하려면 생성자 선언 시 매개변수를 그냥 나열하면 된다.
class Player {
final String name; // 멤버 변수
int age;
bool isAdult;
void sayHello() { // 메소드
print('Hello, my name is $name');
}
Player(this.name, this.age, this.isAdult); // 생성자
}
void main() {
var player1 = Player('지은', 27, true);
var player2 = Player('지지', 13, false);
print(player1.name); // 지은
print(player2.name); // 지지
}
: 생성자 호출 시 매개변수의 이름과 값을 명시적으로 지정하여 값을 전달하는 방법
Named parameters를 사용하려면 생성자 선언 시 매개변수를 중괄호({}
)로 감싸주면 된다.
필요한 경우, required
키워드를 사용해 null 에러를 방지할 수 있다.
class Player {
final String name;
int age;
bool isAdult;
Player({required this.name, required this.age, required this.isAdult});
}
void main() {
var player1 = Player(
name: '지은',
age: 27,
isAdult: true
);
var player2 = Player(
name: '지지',
age: 13,
isAdult: false
);
print(player1.name); // 지은
print(player2.name); // 지지
}
: 클래스 내에 여러 생성자를 정의할 때 사용하며, 생성자를 호출할 때 생성자의 이름을 명시적으로 지정하는 방식이다.
Named Constructor는 클래스 이름 다음에 .constructorName
형식으로 작성하고, 중괄호({}
) 내부에 필요한 매개변수를 작성하면 된다.
Named Constructor는 기본 생성자와 다르게 이름을 가지고 있으며, 이를 통해 여러 생성자 시나리오를 만들 수 있다.
Named Constructor를 정의하는 방법은 아래와 같다.
class 클래스명 {
// 멤버 변수(field) 정의
// 기본 생성자(unnamed constructor) 정의
클래스명(파라미터1, 파라미터2...) {
// 생성자에서 멤버 변수 초기화
}
// named constructor 정의
클래스명.생성자명({ 생성자 파라미터1, 생성자 파라미터2... }) {
// 생성자에서 멤버 변수 초기화
}
}
아래 코드에서 Player
클래스는 Player.createBluePlayer
와 Player.createRedPlayer
두 개의 Named Constructor를 가지고 있으며,
createBluePlayer
생성자는 인스턴스를 생성할 때, team 값을 "blue"로 초기화하고, createRedPlayer
생성자는 team 값을 "red"로 초기화한다.
class Player {
final String name;
int age;
String team;
Player({
required this.name,
required this.team,
required this.age,
});
Player.createBluePlayer({
required String name,
required int age
}) : this.name = name, // 클래스를 초기화
this.age = age,
this.team = 'blue'; // 기본값을 줄 수 있다.
Player.createRedPlayer({
required String name,
required int age
}) : name = name, // 클래스를 초기화
age = age,
team = 'red'; // 기본값을 줄 수 있다.
}
void main() {
var player1 = Player.createBluePlayer(
name: '지은',
age: 27,
);
var player2 = Player.createRedPlayer(
name: '지지',
age: 13,
);
print(player1.name); // 지은
print(player2.name); // 지지
}
이렇게 Named Constructor를 사용하면 객체 초기화를 더 명확하게 정의할 수 있고, 다양한 초기화 옵션을 제공할 수 있다.
콜론(
:
)Dart에서 콜론(
:
)은 주로 초기화 목록(Initialization List)나 부모 클래스의 생성자를 호출하는 데 사용된다.초기화 목록(Initialization List)
: 생성자 내부에서 클래스의 멤버 변수를 초기화하는 특별한 구문으로 생성자의 중괄호(
{}
) 이전에 작성된다.
초기화 목록을 사용하여 객체의 멤버 변수를 초기화하고, 생성자 본문 내에서 초기화하지 않고도 변수를 설정할 수 있다.class ClassName { final String field1; int field2; // 생성자 ClassName( this.field1, this.field2 ) : field2 = field2 * 2, field1 = 'Hello'; }
위의 코드에서
field1
과field2
라는 멤버 변수가 있고, 생성자에서 이 변수들을 초기화하는데, 이때 초기화 목록을 이용해서field2
를 2배로 곱하고,field1
을 'Hello'로 설정하고 있다.이렇게 초기화 목록을 사용하면 생성자 본문 내에서 변수를 초기화할 필요 없이 필드를 초기화할 수 있어 더 효율적이다.
아래 코드는 API 요청을 통해 받아온 JSON 데이터를 Named Constructor를 이용해 Player 객체로 변환하는 예시이다.
Dart에서 데이터를 객체로 변환하는 데 자주 사용되는 패턴이다.
class Player {
final String name;
int age;
String team;
void sayHello() {
print('Hi, my name is $name');
}
// JSON 데이터를 Player 객체로 변환하는 목적으로 정의된 Named Constructor
// Map<String, dynamic> 형식의 playerJson 매개 변수를 받는다.
Player.fromJson(Map<String, dynamic> playerJson) :
name = playerJson['name'], // 매개변수를 사용해 멤버 변수를 초기화한다.
age = playerJson['age'],
team = playerJson['team'];
}
void main() {
var apiData = [
{
'name': '지은',
'age': 25,
'team': 'blue',
},
{
'name': '지지',
'age': 13,
'team': 'red',
},
{
'name': '벨라',
'age': 11,
'team': 'red',
},
];
// forEach를 이용해 apiData 리스트의 각 JSON 객체를 순회하고,
// 각 JSON 객체를 Player.fromJson 생성자를 사용해 Player 객체로 변환한다.
apiData.forEach((playerJson) {
var player = Player.fromJson(playerJson);
player.sayHello(); // 변환된 Player 객체에 sayHello() 메소드를 호출하여 메세지를 출력한다.
// Hi, my name is 지은
// Hi, my name is 지지
// Hi, my name is 벨라
});
}
정리가 항상 잘되있으셔서 보기 편합니다 !