[플러터] 2. 다트 객체지향 프로그래밍

Jun·2024년 2월 11일
0

이번 장은 다트 언어로 객체지향 프로그래밍에 대해 소개한다.

클래스

class Idol {
  String name = '블랙핑크';
  
  void sayName() {
    print('저는 ${this.name}입니다.');
    print('저는 $name입니다.'); // 스코프안에 name이 하나만 있다면 this 생략 가능
  }
}

void main() {
  Idol blackPink = Idol();
  blackPink.sayName();
}

생성자

생성자에서 입력받을 변수를 일반적으로 final로 선언합니다.
인스턴스화한 다음에 혹시라도 변수의 값을 변경하는 실수를 막기 위함입니다.
생성자는 클래스와 같은 이름으로 선언합니다.

class Idol {
  final String name;
  
  Idol(String name) : this.name = name;
  // Idol(this.name); this를 사용할 경우 해당되는 변수에 자동으로 저장됩니다. 
  
  void sayName() {
    print('저는 ${this.name}입니다.');
  }
}

void main() {
  Idol blackPick = Idol('블랙핑크');
  blackPink.sayName();
}

네임드 생성자

네임드 생정자는 네임드 파라미터와 비슷한 개념입니다.
일반적으로 클래스를 생성하는 여러 방법을 명시하고 싶을 때 사용합니다.
아래 예시는 일반적인 생성자와 Map을 파라미터로 받는 생성자를 보여줍니다.

class Idol {
  final String name;
  final int memberCount;
  
  Idol(String name, int memberCount)
    : this.name = name, // , 기호로 여러 변수를 저장할 수 있습니다.
      this.memberCount = memberCount;  
  // Idol (this.name, this.memberCount);
  
  Idol.fromMap(Map<String, dynamic> map)
    : this.name = map['name'],
      this.memberCount = map['memberCount'];
  
  void sayName() {
    print('이름은 $name이고 $memberCount명입니다.');
  }
}

void main() {
  Idol blackPink = Idol('블랙핑크', 4);
  blackPink.sayName();
  
  Idol bts = Idol.fromMap({
    'name': 'BTS',
    'memberCount': 7,
  });
  bts.sayName(); // 이름은 BTS이고 7명입니다.
}

프라이빗 변수

다트에서 프라이빗 변수는 클래스 내부에서만 사용하는 변수가 아닌, 같은 파일에서만 접근 가능한 변수입니다.

class Idol {
  String _name;
  
  Idol(this._name);
}

void main() {
  Idol blackPink = Idol('블랙핑크');
  print(blackPink._name); // 같은 파일에서는 _name에 접근 가능하지만, 다른 파일에선 불가능 합니다.
}

getter / setter

class Idol {
  String _name;
  
  Idol(this._name);
  
  String get name {
    return this._name;
  }
  
  set name(String name) {
    this._name = name;
  }
}

void main() {
  Idol blackPink = Idol('블랙핑크');
  blackPink.name = '에이핑크';
  print(blackPick.name); // 에이핑크
}

상속

class Idol {
  final String name;
  
  Idol(this.name);
  
  void sayName() {
    print('저는 $name입니다.');
  }
}

class BoyGroup extends Idol {
  BoyGroup(String name) : super(name);
  // BoyGroup(super.name);
  
  void sayMale() {
    print('저는 남자 아이돌입니다.');
  }
}

void main() {
  BoyGroup bts = BoyGroup('BTS');
  bts.sayName();
  bts.sayMale();
}

오버라이드

class GirlGroup extends Idol {
  GirlGroup(super.name);
  
  void sayName() {
    print('저는 여자 아이돌 $name입니다.');
  }
}

void main() {
  GirlGroup blackPink = GirlGroup('블랙핑크');
  blackPink.sayName(); // 저는 여자 아이돌 블랙핑크입니다.
}

인터페이스

인터페이스는 변수, 메서드의 이름만 같고 모든 기능은 새로 다시 정의해주어야 합니다.
인터페이스는 특정 클래스가 반드시 같은 이름을 같는 변수와 메서드를 사용해야할 때 유용합니다.

class Idol {
  final String name;
  
  void sayName() {}
}

class GirlGroup implements Idol {
  final String name;
  
  GirlGroup (this.name);
  
  void sayName() {
    print('저는 여자 아이돌 $name입니다.');
  }
}

void main() {
  GirlGroup blackPink = GirlGroup('블랙핑크');
  blackPink.sayName();
}

믹스인

믹스인은 특정 클래스에 원하는 기능들만 골라넣을 수 있는 기능입니다.

mixin IdolSingMixin on Idol {
  void sing() {
    print('$name이 노래를 부릅니다.');
  }
}

class BoyGroup extends Idol with IdolSingMixin {
  BoyGroup(super.name);
  
  void sayMale() {
    print('저는 남자 아이돌입니다.');
  }
}

void main() {
  BoyGroup bts = BoyGroup('BTS');
  bts.sing();
}

추상 클래스

추상 클래스는 변수, 메서드 이름만 정의되어 있고, implements나 extends를 통해 기능을 정의하거나 추가합니다.

abstract class Idol {
  final String name;
  
  Idol(this.name);
  
  void sayName();
}

class GirlGroup implements Idol {
  final String name;
  
  GirlGroup(this.name);
  
  void sayName() {
    print('$name입니다.');
  }
}

void main() {
  GirlGroup blackPink = GirlGroup('블랙핑크');
  blackPink.sayName();
}

제네릭

제네릭은 클래스나 함수의 정의를 선언할 때가 아니라 인스턴스화 하거나 실행할 때로 미룹니다.
특정 변수의 타입을 하나의 타입으로 제한하고 싶지 않을 때 자주 사용합니다.

class Cache<T> {
  final T data;
  
  Cache({
    required this.data,
  });
}

void main() {
  final cache = Cache<List<int>>(
    data: [1, 2, 3],
  );
  
  print(cache.data.reduce((v, e) => v + e)); // 6
}

Static

static은 인스턴스끼리 공유해야하는 정보를 위해 사용합니다.

class Counter {
  static int i = 0;
  
  Counter() {
    print(i++);
  }
}

void main() {
  Counter count1 = Counter(); // 1
  Counter count2 = Counter(); // 2
}

캐스케이드 연산자

캐스케이드 연산자는 인스턴스에서 해당 인스턴스의 속성이나 멤버 함수를 연속해서 사용하는 기능입니다.
... 기호를 사용합니다.

void main() {
  Idol blackPink = Idol('블랙핑크')
    ...sayName(); // 저는 블랙핑크입니다.
    
  blackPick...sayName()...sayMemeberCount();
}

《Must Have 코드팩토리의 플러터 프로그래밍 2판》의 스터디 내용 입니다.

profile
HiHi

0개의 댓글