[Dart] 클래스와 친구들

김정현·2024년 1월 23일
1

Dart

목록 보기
3/3

💡 이 글은 "깡샘의 플러터&다트 프로그래밍" 도서에서
'클래스와 생성자' & '상속과 추상 클래스' 내용을 바탕으로 정리한 것입니다.

  • 생성자

    Dart의 클래스는 다른 객체지향 언어의 클래스와 비슷하지만 몇 가지 독특한 내용을 정리해본다.

    • 멤버 초기화 생성자 단순화

      class User {
        late String name;
        late int age;
        User(this.name, this.age);  // this 키워드로 멤버 바로 초기화
       }
    • 초기화 목록(Initializer list)

      // ':' 사용한 초기화 목록
      User(String name, int age) : this.name = name, this.age = age { }
      // 리스트 데이터로 초기화
      class MyClass { 
        late int data1;
        late int data2;
      
        MyClass(List<int> args) 
          : this.data1 = args[0],
            this.data2 = args[1] { }
      }
      // 멤버 함수 반환값으로 초기화
      class MyClass { 
        late int data1;
        late int data2;
      
        MyClass(int arg1, int arg2)
          : this.data1 = calFun(arg1),
            this.data2 = calFun(arg2) { } 
            
        static int calFun(int arg) {
          return arg * 10; 
        }
      }
    • 명명된 생성자(Named Constructor)
      생성자 오버로딩대신 이름이 있는 생성자를 여러 개 선언하는 기법

      // 명명된 생성자
      class MyClass {
        late imt data1;
        late imt data2; 
        
        MyClass(this.data1, this.data2);
        MyClass.first(int arg) : this(arg, 0);  // 기본 생성자(MyClass) 호출
        MyClass.second() : this.first(0);       // 명명된 생성자(MyClass.first) 호출
      }
    • 팩토리 생성자(Factory Constructor)
      클래스 외부에서는 생성자처럼 이용하지만 실제로 객체를 생성하진 않고, 상황에 맞는 객체를 반환하는 역할
      캐시 알고리즘이나 상속 관계에 따른 다형성 구현 시 유용.

      // 캐시 알고리즘 구현 예
       class Image {
         late String url;
         static Map<String, Image> _cache = 〈String, Image>{};
         Image._instance(this.url);           // named constructor
         factory Image(String url) {
           if (_cache[url] == null) {         // 전달받은 식별자가 캐시에 없으면
             var obj = Image.instance(url);   // 해당 식별자로 객체를 새로 생성하고 
             _cache[url] = obj;               // 캐시에 추가
           }
           return _cache[url]!;               // 캐시에서 식별자에 해당하는 객체 반환
         }
       }
      
       main() {
         var imagel = Image('a.jpg');
         var image2 = Image('a.jpg');
         print('image1 == imaged : ${image1 == image2}');  // image1 == image2 : true
       }
  • 상속과 추상 클래스

    다른 객체지향 언어와 큰 차이는 없다.

    • 상속, 오버라이딩, 부모 클래스 멤버 접근

      // 함수 객체 활용 예
       class SuperClass {
         int myData = 10;
         void myFun() {
           print ('Super..myFun()...');
         }
       }
       
       class SubClass extends Superclass {    // 'extends' 키워드로 상속
         int myData = 20;
         void myFun() {
           super.myFun();    // 'super' 키워드로 부모 클래스 멤버 접근
           print('Sub..myFun()..myData : $myData, super.myData : ${super.myData}');  // 'super' 키워드로 부모 클래스 멤버 접근
         }
       }
       
       main(List<String> args) {
         var obj = SubClass();
         obj.myFun();
       }
      // 실행 결과
       Super..myFun()...
       Sub..myFun()..myData : 20, super.myData : 10
    • 부모 생성자 호출 및 멤버 초기화

      // 부모 클래스 생성자 호출 및 멤버 변수 초기화
       class Superclass {
         String name;
         int age;
         SuperClass(this.name, this.age) {}
       }
       
       class SubClass1 extends Superclass {
         SubClass(String name, int age) : super(name, age) {}    // 부모 클래스 멤버 초기화
       }
       
       class SubClass2 extends Superclass {
         SubClass(super.name, super.age); 
       }
       
       main() {
         var obj1 = SubClass1('kkang', 10);
         print('${obj1.name}, ${obj1.age}');
         var obj2 = SubClass2('kkim', 20);
         print('${obj2.name}, ${obj2.age}');
       }
      // 실행 결과
       kkang, 10
       kkim, 20
    • 추상 클래스

      // 추상 클래스 선언 및 재정의
       abstract class User {    // 'abstract' 키워드로 추상 클래스 선언
         void some();
       }
       
       class Customer extends User {
         
         void some() {} 
       }
    • 인터페이스

      // 일반 클래스
       class User { 
         String name;
         User(this.name);
         String greet(String who) => 'Hello, $who. I'm $name';
       }
       
       // 'implements' 키워드로 인터페이스 구현 클래스 선언
       class MyClass implements User {    // User는 암시적 인터페이스 역할
         String name = 'kim';
         
         String greet(String who) => return 'hello';
       }
       
       main() {
         User user = MyClass();    // 구현 클래스 객체는 인터페이스 타입으로 선언 가능
       }
    • 믹스인(Mixin)
      믹스인은 변수와 함수는 선언할 수 있지만 클래스가 아니므로 생성자가 없다.
      하지만 내부에 선언된 멤버들을 다른 클래스에 상속한 것처럼 이용할 수 있다.

      // 믹스인을 다중 상속처럼 활용한 예
       mixin MyMixin {    // 'mixin' 키워드로 믹스인 선언
         int mixinData = 10; 
         void mixInFun() {
           print ('MyMixin...mixInFun()...'); 
         }
       }
       
       class MySuper {
         int superData = 20;
         void superFun() {
           print('MySuper... superFun()');
         }
       }
       
       // 다중 상속처럼 선언
       class MyClass extends MySuper with MyMixin {   // 'with' 키워드로 믹스인 멤버 사용 선언
         void sayHello() {
           print('class data : $superData, mixin data : $mixinData');
           mixInFun();
           superFun();
         }
       }
      
       main() {
         var obj = MyClass();
         obj.sayHello();
       }
      // 실행 결과
       class data : 20, mixin data : 10
       MyMixin... mixInFun()...
       MySuper...superFun()
profile
하고풍거(河鼓風去) 삭다하자(削多㰤慈)

0개의 댓글