다트에서의 클래스는 매우 중요하다. 자바처럼 클래스로 이루어져있기 때문이다.
우선 클래스를 만들어보자
class Player{
String name = "chobkyu";
}
.
이렇게 만들면 Player라는 이름에 name이라는 프로퍼티를 가진 클래스를 만들 수 있다. 클래스를 생성할 때는 함수에서 변수를 사용할 때와는 달리 변수에 타입을 꼭 명시해주어야 한다. 그리고 만약 변수를 수정할 수 없게 해놓고 싶다면 타입 앞에 final을 붙여주면 된다. Player 클래스를 좀 더 작성해보자.
class Player{
final String name = 'chobkyu'; //final 변수는 수정 불가
int xp = 1500;
void sayHello(){
print("hi my name is $name"); //클래스 함수 내에서는 this를 쓸 필요가 없음
}
}
int 타입의 변수 xp와 sayHello 함수가 추가 되었다. 여기서 클래스 함수 내에서 변수를 호출할 때 this를 쓸 필요가 없다는 것을 알 수 있다. 물론 함수 내에 동일한 이름의 변수가 존재할 때는 어쩔 수 없이 this를 써야 하지만 그 외의 경우에는 this를 쓰지 않는 것을 권장한다고 한다. 이제 메인함수에서 클래스의 인스턴스를 만들고 변수와 함수에 접근해보자.
void main() {
var player = Player(); //꼭 new를 붙일 필요가 없음
player.sayHello();
print(player.name); //변수 접근
}
보면 그냥 Player()로 new를 붙이지 않고 인스턴스를 생성했다. 프로퍼티에 접근하는 건 다른 언어와 비슷하다.
생성자
생성자는 자바를 배웠다면 알다시피 인스턴스가 생성될 때 호출되는 인스턴스 초기화 메소드라고 할 수 있다. 인스턴스 변수의 초기화 작업에 주로 사용되며 인스턴스 생성 시에 실행되어야 할 작업을 위해서도 생성된다. 생성자를 작성해보자
class Player{
late String name; //생성자로 값을 받아오기 전에 값을 주지 않으면 에러남
late int xp ; //따라서 변수들의 값을 나중에 받아올거라는 의미인 late를 타입 앞에 작성
Player(String name, int xp){
this.name = name;
this.xp = xp;
}
void sayHello(){
print("hi my name is $name"); //클래스 함수 내에서는 this를 쓸 필요가 없음
}
}
클래스 명과 동일한 이름을 가진 함수를 만들었다. 이 생성자 함수를 통해 변수들을 받아와 name과 xp 변수의 값을 초기화 해줄 것이다. 이러기 위해서는 변수 위에 초기값을 입력해줘야 하는데 그렇지 않으면 dart는 에러를 뱉어내기 때문이다. 하지만 무턱대고 아무 값이나 초기 값으로 줄 수는 없으니 late로 변수 선언은 지금하지만 값은 나중에 받아올 것이라고 명시를 해주어야 한다.
이렇게 생성자를 만들게 되면
void main() {
var player1 = Player("chobkyu",1500);
player1.sayHello();
print(player1.name);
var player2 = Player("qudqud97",1400);
player2.sayHello();
print(player2.name);
}

이렇게 인스턴스를 생성하고 생성자를 통해 인자를 넘겨서 초기 값을 설정할 수 있다.
여기서 생성자를 더 간단하게 만들 수 있는데 Player 클래스에서 이미 변수 선언 시에 타입을 명시해주었기 때문에 굳이 생성자에서도 타입을 명시할 필요가 없고 생성자의 인자가 바로 변수에 저장되기 때문에 this.name = name 같은 코드도 생략이 가능하다.
class Player{
String name;
int xp ;
Player(this.name, this.xp);
void sayHello(){
print("hi my name is $name"); //클래스 함수 내에서는 this를 쓸 필요가 없음
}
}
이렇게 작성하면 굳이 변수 선언 시에 late를 작성할 필요도 없고 생성자에서 받은 인자를 바로 변수에 깔끔하게 저장할 수 있다. 이렇게 되면 인스턴스 생성 시 위치로 각 변수에 값을 할당할 수 있다.

하지만 이 방식은 class의 규모가 커지면, 다시 말해 클래스 내에 변수들이 많아지면 어려움에 처할수 있다. 너무 많은 positional argument가 모여있으면 혼란스러울 수 있다.

이 때 Named Constructor Parameters를 사용할 수 있다. 먼저 생성자의 파라미터 부분을 {}로 감싸준다.

이렇게만 작성하게 되면 각 변수에 null이 올 수 있다고 에러가 난다. 이를 막기 위해선 초기값을 주는 방법도 있지만 무조건 값을 할당해야된다는 옵션인 required를 붙여주는게 깔끔하다.

이런 다음 인스턴스를 생성할 때 다음과 같이 이름을 붙여서 파라미터를 넘겨주면 된다.

당연히 Dart는 각 변수들이 required (각각의 타입)을 알고 있어 값을 할당하지 않거나 잘못된 타입을 적었으면 에러를 뱉어내게 된다.
Named Constructor
Contructor를 만들 때 조금 다르게 동작하는 다른 Constructor를 만들고 싶을 때가 있다. 예를 들면 위 클래스에서 한 생성자는 블루팀에 xp가 1500이고 한 생성자는 레드팀에 xp가 1000인 인스턴스를 만들어야하는 상황이다. 즉 사용자로부터 name과 age의 값만 전달 받고 팀과 xp는 원하는 값을 할당하는 것이다. 먼저 인스턴스는 name과 age를 받아야하니 다음과 같이 생성하는데 이때 메서드를 붙여서 생성한다.
var player1 = Player.createBluePlayer(
name:"chobkyu",
age:26,
);
그런 다음 클래스에 다음과 같이 작성한다.
class Player{
String name;
int xp;
String team;
int age;
Player({required this.name,required this.xp,required this.team,required this.age});
Player.createBluePlayer({
required String name,
required int age
}) :
this.age =age, this.name = name, this.team = 'blue', this.xp=0;
void sayHello(){
print("hi my name is $name"); //클래스 함수 내에서는 this를 쓸 필요가 없음
}
}
보면 createBluePlayer 메소드를 작성했다. name과 age라는 두 개의 named 된 파라미터를 받고 있다. 그리고 콜론을 사용해 Player 클래스를 초기화 시켜준다. name과 age엔 생성자에서 전달 받은 값을 넣어주고 team하고 xp에는 각각의 기본 값이 들어가게 한다. 즉 createBluePlayer는 Player 객체를 만들고 : 을 이용해서 Player 객체를 초기화 해주는 것이다. 이런 식으로 다른 named constructor를 만들 수 있다.

이렇게 하면 밑에 createRedPlayer는 Player 객체를 만들고 name과 age는 전달 받은 값을, team과 xp에는 각각 'Red'와 10이라는 기본값을 할당하게 된다.
'프로그래밍 언어 > Dart' 카테고리의 다른 글
[Dart] 추상화 클래스와 상속, Mixin (0) | 2023.10.25 |
---|---|
[Dart] Cascade Notation (0) | 2023.10.25 |
[Dart] 함수 (0) | 2023.02.26 |
[Dart] 자료형 (0) | 2023.02.22 |
[Dart] Dart를 시작해보자 (0) | 2023.02.21 |