상세 컨텐츠

본문 제목

생성자 파헤치기 (Constructor)

앱개발/Dart

by 호치민 개발자 2023. 7. 31. 17:28

본문

1) 기본 생성자
2) 이름있는 생성자(Named Constructor)


클래스에는 생성자가 따른다. 생성자는 이름처럼 클래스가 인스턴스화 될 때, 즉 객체가 생성될 때 호출된다 

1)기본 생성자

클래스를 구현할 때 생성자를 선언하지 않는 경우 / 생략한 경우 => 기본 생성자가 자동으로 생성됨 

기본 생성자는

- 클래스명과 동일하면서 인자가 없다.

- 부모 클래스의 인수가 없는 생성자(=기본 생성자)를 호출한다.

 

기본 생성자의 형태 

class 클래스이름{
  클래스명(){
  }
}

예시)
class Food{
 Food(){
 }
}

부모 클래스는 자식 클래스에게 상속이 가능한 관계이다. 아래와 경우는 Food 클래스가 부모 클래스이며 Ramen클래스가 자식이다. 

extends 키워드가 부모 / 자식 관계를 지정하는 역할을 한다. 

class Food {
  Food() {
    print('This is Food 생성자');
  }
}

class Ramen extends Food {}

main() {
  var ramen = Ramen();
}

//결과: 
This is Food 생성자

Ramen클래스에는 생성자가 없다. 그러므로 자동자으로 기본 생성자가 제공되는것이다. 

[- 부모 클래스의 인수가 없는 생성자(=기본 생성자)를 호출한다.] 위에서 작성했듯이 부모인 Food클래스의 기본 생성자가 호출되었다.

 

생성자가 호출되는 순서를 확인하고 싶다면 아래와 같이 작성해볼 수 있다 

class Food {
  Food() {
    print('This is Food 생성자');
  }
}

class Ramen extends Food {
  Ramen(){
    print('This is Ramen Constructor !');
  }
}

main() {
  var ramen = Ramen();
}

//결과:
This is Food 생성자
This is Ramen Constructor !

 

 

2)이름 있는 생성자

사실 강의에서 Named constructor로 부른 이 생성자를 이해하기 위해 작성한 포스트이다.

 

말 그대로 생성자에게 이름을 부여한 형태이다. 한 클래스 내에 많은 생성자(Contructor)를 만들거나, 생성자를 명확히 하기 위해 사용한다.

class 클래스이름{
  클래스명.생성자명(){
  }
}

예시)
class Food{
 Food.init(){
 }
}

 

다음과 같이 Food.init()이라는 Named Constructor를 선언해보자.

class Food {
  Food() {
    print('This is Food 생성자');
  }
  Food.init() {
    print('This is Food의 이름있는 생성자');
  }
}

class Ramen extends Food {
  Ramen(){
    print('This is Ramen Constructor !');
  }
}

main() {
  var ramen = Ramen();
  var init = Food.init();
}

//결과:
This is Food 생성자
This is Ramen Constructor !
This is Food의 이름있는 생성자

중요) 기본 생성자는 단 하나만 있어야 하며, Named Constructor를 선언하면 기본 생성자는 생략할 수가 없다

 

1)) 기본 생성자 2개 선언했을 경우: 중복 선언 에러 발생

class Food {
  Food() {
    print('This is Food 생성자');
  }
  Food(String name) {
    print('This is ($name)의 두번째 기본 생성자');
  }
}

class Ramen extends Food {
  Ramen(){
    print('This is Ramen Constructor !');
  }
}

main() {
  var ramen = Ramen(); 
}


//결과:
Error compiling to JavaScript:
Info: Compiling with sound null safety.
lib/main.dart:5:3:
Error: 'Food' is already declared in this scope.
  Food(String name) {
  ^^^^
lib/main.dart:2:3:
Info: Previous declaration of 'Food'.
  Food() {
  ^^^^
Error: Compilation failed.

이름있는 생성자로 변경하면 에러 수정됨

class Food {
  Food() {
    print('This is Food 생성자');
  }
  Food.init(String name) {
    print('This is ($name)의 두번째 생성자');
  }
}

class Ramen extends Food {
  Ramen(){
    print('This is Ramen Constructor !');
  }
}

main() {
  var ramen = Ramen(); 
  var init = Food.init('Jason');
}

//결과:
This is Food 생성자
This is Ramen Constructor !
This is (Jason)의 두번째 생성자

 

2)) Named Constructor를 선언하면 기본 생성자는 생략할 수가 없다 // 라고 위에 작성했으나,

다음의 경우에는 기본 생성자가 없다. 결과도 에러없이 출력된다. 어떻게 된 일이지??...

class Food {
   Food.init(String name) {
    print('This is ($name)의 생성자');
  }
}


main() {
  var init = Food.init('Jason');
}

//결과:
This is (Jason)의 생성자

아래와 같이 직접 기본 생성자를 불러보면 이제서야 에러가 확인된다.

즉 생략이 불가능하므로, 자동적으로 동작하지 않는것이다.

class Food {
   Food.init(String name) {
    print('This is ($name)의 생성자');
  }
}


main() {
  var food = Food();
  var init = Food.init('Jason');
}
//결과:
Error compiling to JavaScript:
Info: Compiling with sound null safety.
lib/main.dart:9:14:
Error: Couldn't find constructor 'Food'.
  var food = Food();
             ^^^^
Error: Compilation failed.

아래와 같이 기본 생성자를 제대로 써주니 해결된다 

class Food {
  
  Food(){
    print('This is 살아난 기본 생성자');
  }
   Food.init(String name) {
    print('This is ($name)의 생성자');
  }
}


main() {
  var food = Food();
  var init = Food.init('Jason');
}

//결과:
This is 살아난 기본 생성자
This is (Jason)의 생성자

관련글 더보기