
생성자
객체를 생성하고 초기화하기 위해 사용하는 특수한 메서드
기본 생성자 (Default Constructor)
- 매개변수를 갖지 않는 생성자
Class();
- 자동으로 정의되기 때문에 클래스에 따로 명시하지 않아도 됨.
- 인스턴스 변수들이 모두 초기화되어 있는 상태여야 함.
<가능>
class Car {
String name = "";
List<String> models = [];
Car();
}
<불가능>
class Car {
String name;
List<String> models;
Car();
}
/* 불가능한 이유: String, List<String>은 non-nullable 타입. 그런데 기본값도 없고 생성자도 초기화 하지 않았으므로 Dart 컴파일러는 'Car() 생성자가 끝났는데, 속성에 값이 들어갈 보장이 없다'라고 판단하여 에러 처리함.*/
<가능>
class Car {
String? name;
List<String>? models;
Car();
}매개변수 생성자 (Parameterized Constructor)
- 매개변수를 갖는 생성자
- 매개변수를 통해 외부에서 인스턴스 변수들의 초기값을 설정.
Class(this.변수);
class Car {
String name;
List<String> models;
Car(this.name, this.models);
}Car(this.name, this.models)를 통해 받아온 this.name 과 this.models 가
Car의 변수인 name과 models에 대입Class(type parameter) : variable = parameter;
class Car {
String name;
List<String> models;
Car(String name, List<String> models)
: this.name = name,
this.models = models;
}
void main() {
Car car = Car("BMW", ['320i', '340i', 'M3']);
print(car.name); // BMW
print(car.models); // ['320i', '340i', 'M3']
print(car.models.join(', ')); // ['320i', '340i', 'M3']
}
생성자 단계에서 필드를 바로 초기화 하는 방식 → 보다 안전하고 Dart가 권장하는 방식
Dart 컴파일러가 non-null 보장을 명확히 확인 가능.
“이 객체는 태어나는 순간부터 name과 models가 반드시 값을 가진다.”
null-safety를 명확히 보장함.
⇒
final 필드 가능class Car {
final String name;
final List<String> models;
Car(String name, List<String> models)
: name = name,
models = models;
}Class(type parameter) {this.variable;}
class Car {
String name = "";
List<String> models = [];
Car(String name, List<String> models) {
this.name = name;
this.models = models;
}
}
void main() {
Car car = Car("BMW", ["3, 5, 7"]);
print(car.name);
print(car.models.join(', '));
}
일단 기본값으로 만든 뒤, 생성자 본문에서 다시 대입하는 방식.
객체 생성 후 본문 실행 시점에 대입. 필드에 임시 기본값이 먼저 필요함.
= 일단 빈 값으로 인스턴스를 생성하고, 생성자 실행 중에 값이 바뀐다.
생성자 안에서 조건문, 로직, 계산, 검증 등의 이유로 초기값을 상황에 따라 바꿔야 할 때.
<예시>
Car(String name, List<String> models) {
if (models.isEmpty) {
this.models = ['기본 모델'];
} else {
this.models = models;
}
}⇒
final 필드 불가능class Car {
final String name;
final List<String> models;
Car(String name, List<String> models) {
this.name = name; // 불가능
this.models = models; // 불가능
}
}⇒
final 필드는 반드시 initializer list에서 초기화 해야 함.- 객체 생성 시 매개변수를 넣지 않으면 오류 발생
네임드 생성자 (Named Constructor)
- 클래스 메서드와 같은 형식으로 호출하는 생성자
Class.method(type parameter) : variable = parameter;
class Car {
String name;
List<String> models;
Car.fromList(List values)
: this.name = values[0],
this.models = values[1];
void speakName() {
print("저희는 $name입니다.");
}
void speakModels() {
print("$models 모델을 가지고 있습니다.");
}
}
void main() {
Car car = Car.fromList([
'BMW',
['320i', '340i', 'M3']
]);
car.speakName(); // 저희는 BMW입니다.
car.speakModels(); // [320i, 340i, M3] 모델을 가지고 있습니다.
}- 클래스와 이름이 동일.
- 반환값이 없기 때문에
void타입.
- 클래스를 통해 객채가 생성될 때 자동으로 호출됨.
- 생성할 수 있는 객체의 수에 제한이 없음.
class Person {
String name;
int age;
Person(this.name, this.age);
Person.paul(int age) : name = "Paul", age = age;
Person.mark(int age) : name = "Mark", age = age;
@override
String toString() {
return ("$name, $age세");
}
}
void main() {
Person paul = Person.paul(25);
Person mark = Person.mark(30);
print(paul); // Paul, 25세
print(mark); // Mark, 30세
}- 하나의 클래스로 여러 객체를 생성할 수 있기 때문에 공통된 속성과 동작을 갖는 코드를 여러 번 작성하지 않아도 돼서 재사용성 높은 코드를 만들 수 있음.
제네릭 클래스
Class<type parameter>특정 타입에 의존하지 않고, 여러 타입에 대해 동일한 코드를 적용할 수 있어서 재사용성 높은 코드를 짤 수 있음.
<타입 의존 클래스>
class IntBox {
int value;
IntBox(this.value);
int getValue() {
return value;
}
}
class StringBox {
String value;
StringBox(this.value);
String getValue() {
return value;
}
}
void main() {
var intBox = IntBox(10);
print(intBox.getValue()); // 10
var stringBox = StringBox("Hello");
print(stringBox.getValue()); // Hello
}<제네릭 클래스>
class Box<T> {
T value;
Box(this.value);
T getValue() {
return value;
}
}
void main() {
var intBox = Box<int>(10);
print(intBox.getValue()); // 10
var stringBox = Box<String>("Hello");
print(stringBox.getValue()); // Hello
}실습
원의 반지름을 속성으로 가지고 있는 Circle 클래스를 만들어보세요.
반지름은 생성자를 통해서 전달받아서 넓이를 계산하는 메서드도 만들어 본 후 넓이를 출력해보세요.
class Circle {
static double pi = 3.14;
double radius = 0;
Circle(this.radius);
double area() {
return (radius * radius * pi);
}
}
void main() {
Circle a = Circle(10);
print(a.area()); // 314
Circle b = Circle(20);
print(b.area()); // 1256
Circle c = Circle(100);
print(c.area()); // 31400
}Share article