Dart 문법

클래스 생성자 방식

hamiric 2024. 11. 18. 14:43

클래스 생성자

생성자는 인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메서드'로써, 인스턴스 변수의 초기화 작업에 주로 사용되며, 인스턴스 생성 시에 실행 되어야 할 작업을 위해서도 사용되는 메서드이다.

 

  • 클래스 생성자 기본형
// 생성자 기본형
class Human {
    String name;
    int age;
    bool sex;
    
    Human(String name, int age, bool sex){
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
}

 

 

  • 형식 매개변수 초기화 ( Initializing formal 방식 )

Initializing formal은 생성자에서 선언된 파라미터가 해당 클래스의 멤버 변수에 값을 할당하는 역할을 한다는 의미이다. 즉, 이 방식은 클래스를 생성할 때 객체를 초기화하는 데 사용되며, 생성자에서 멤버변수를 쉽게 초기화 할 수 있도록 해주며, 별도의 코드 없이 간결하게 값을 할당해 줄 수 있도록 한다.

// Initializing formal 방식 기본형
class Point {
  final double x;
  final double y;

  Point(this.x, this.y);
}
// Initializing formal 방식 - named parameters(명명된 매개변수)
// {} 안의 매개변수는 optional 한 매개변수
class Person {
  String name;
  int? age;
  bool? sex;

  Person(this.name, {this.age, this.sex});
}

// named parameters 방식을 사용할때
// named를 넣어서 생성해 주어야 한다.
Person('Alice', age: 10, sex: false);
// Initializing formal 방식 - positional optional parameters(위치 선택적 매개변수)
// []안의 매개변수는 optional 한 매개변수
class Person {
  String? name;
  int? age;
  bool? sex;

  Person(this.name, [this.age, this.sex]);
}

// positional optional parameters 방식을 사용할때
// 매개변수의 위치를 항상 주의해야 한다.
Person('Alice', 10, false);

 

 

  • 명명된 생성자 방식 (Named Constructor)

명명된 생성자 방식은 여러가지의 초기화 방식이 필요할 때 주로 사용된다.

const double xOrigin = 0;
const double yOrigin = 0;

class Point {
  final double x;
  final double y;

  Point(this.x, this.y);

  // 명명된 생성자
  Point.origin()
      : x = xOrigin,
        y = yOrigin;
}

// 사용방식
var p1 = Point(3, 4);    // 기본 생성자
var p2 = Point.origin(); // 명명된 생성자

 

 

  • 부모 클래스의 Non-default 생성자 호출

부모 클래스의 Non-default 생성자 호출 방식은, 부모의 생성자를 자식의 클래스가 상속하여 사용하고 싶을때 사용한다.

이때, 상속하려는 생성자는 반드시 클래스가 기본 생성하는 생성자가 아니어야 한다.

// 부모 클래스
class Animal {
  String name;

  // Non-default 생성자
  Animal(this.name);

  void speak() {
    print("$name makes a sound");
  }
}

// 자식 클래스
class Dog extends Animal {
  int age;

  // 자식 클래스의 생성자에서 부모 클래스의 Non-default 생성자 호출
  Dog(String name, this.age) : super(name);  // 부모 클래스의 Animal(name) 생성자 호출

  @override
  void speak() {
    print("$name barks");
  }
}

// 사용시
var dog = Dog("Buddy", 5);
dog.speak();  // 출력: Buddy barks

 

 

  • 이니셜라이즈 리스트 (Initializer List)

이니셜라이즈 리스트 방식은 주로 final이나 const 방식의 멤버변수를 초기화할때 사용한다.
이니셜라이즈 리스트는 클래스의 생성자 본문이 실행되기 전에 멤버 변수를 초기화한다.

class Point {
  final double x;
  final double y;

  // 이니셜라이즈 리스트를 사용하여 초기화
  Point(double x, double y)
      : x = x, y = y {
        // 추가적인 초기화 작업
      }
}

 

 

  • 리다이렉팅 생성자 호출 방식 (Redirecting Constructor)

리다이렉팅 생성자는 하나의 생성자에서 다른 생성자를 호출하는 방식으로, 객체를 초기화 할때, 다른 생성자에게 초기화 방식을 위임하는 방식이라고 할 수 있다.

class Rectangle {
  double width;
  double height;

  // 기본 생성자
  Rectangle(this.width, this.height);

  // 리다이렉팅 생성자: 정사각형을 만들 때
  // 기본 생성자를 호출, width와 height를 side값으로 동일하게 설정
  Rectangle.square(double side) : this(side, side);

  double area() => width * height;
}

// 사용시
var rectangle = Rectangle(10, 5);       // 기본 생성자 호출
var square = Rectangle.square(5);       // 리다이렉팅 생성자 호출

print('Rectangle area: ${rectangle.area()}');  // 출력: Rectangle area: 50.0
print('Square area: ${square.area()}');       // 출력: Square area: 25.0

 

 

  • 상수 생성자 (Const Constructor)

해당 클래스가 상수처럼 변하지 않는 객체를 생성하도록 하는 생성자. 즉, 컴파일 타임에 초기화 되어 불변함을 가진다.

상수 생성자를 만들기 위해서는, 모든 멤버변수가 final과 const로 이루어져 있어야 한다.

상수 생성자는 같은 값을 가지는 객체를 재사용하게 함으로써, 메모리를 절약하고 성능을 향상시킬 수 있다.

class Circle {
  final double radius;
  final List<double> dimensions;

  // 상수 생성자
  const Circle(this.radius, this.dimensions);
}

// 사용시
// 상수 생성자를 사용하여 객체를 생성
var circle1 = const Circle(5.0, [5.0, 10.0]);
var circle2 = const Circle(5.0, [5.0, 10.0]);

// 동일한 메모리 주소를 가지는지 체크하는 identical함수
// 두 객체가 동일한 값이므로, 동일한 인스턴스로 간주
print(identical(circle1, circle2));  // 출력: true

 

 

  • Factory 생성자

팩토리 패턴을 사용하여 클래스 생성자를 정의한 방식

특정 클래스의 인스턴스를 반환하는 특별한 생성자로, 일반적인 생성자와는 다르게 새로운 객체를 생성하지 않고 기존 객체를 반환하거나 조건에 따라 다른 종류의 객체를 반환할 수 있다.

// 팩토리 생성자 기본형
class Person {
  final String name;
  final int age;

  // 기본 생성자
  Person(this.name, this.age);

  // 팩토리 생성자
  factory Person.createPerson(String name, int age) {
    if (age < 18) {
      return Person(name, age);  // 일반적인 Person 객체 반환
    } else {
      // 다른 조건을 만족하는 경우
      return Person(name, age);  // 여기도 다른 종류의 객체 반환 가능
    }
  }
}

// 사용시
var person = Person.createPerson("Alice", 25);  // 팩토리 생성자 호출
print('${person.name}, ${person.age}');
// 팩토리 생성자 - 싱글턴 구현
// 동일한 객체 인스턴스를 여러 번 재사용해야 할 때, 인스턴스를 단 하나만 생성하여 재사용 하는 방식
// 싱글턴 패턴을 사용하는 클래스는 기본적으로 인스턴스가 하나만 존재하도록 설계되어야 한다. (권고사항)
class Person {
  final String name;
  final int age;

  // 싱글턴 인스턴스를 저장할 정적 변수
  static Person? _instance;

  // private 생성자
  Person._internal(this.name, this.age);

  // 팩토리 생성자
  factory Person(String name, int age) {
    // 기존 인스턴스가 없으면 새로운 인스턴스 생성
    _instance ??= Person._internal(name, age);
    
    // 기존 인스턴스를 반환
    return _instance!;
  }
}

// 사용시
var person1 = Person('Alice', 25);
// 싱글턴방식의 클래스는 인스턴스가 하나만 존재해야 하기 때문에, person1 값으로 오버라이딩됨
var person2 = Person('Bob', 30);

print('Person1: ${person1.name}, ${person1.age}'); // 출력: Person1: Alice, 25
print('Person2: ${person2.name}, ${person2.age}'); // 출력: Person2: Alice, 25

print(identical(person1, person2)); // 출력: true (두 객체는 동일한 인스턴스)

 

 

 

< 참고 자료 >

 

생성자

Dart 생성자에 대한 모든 것.

dart-ko.dev

 

 

'Dart 문법' 카테고리의 다른 글

JsonData 변환  (0) 2024.11.28
Dart 문법(6)  (0) 2024.11.04
Dart 문법(5)  (0) 2024.11.01
Dart 문법(4)  (0) 2024.10.28
Dart 문법(3)  (0) 2024.10.28