기술은 나의 도구

[노마드코더 플러터] Dart Classes

Dart Class 기본 사용법

class Player {
  String name = 'moz'; // class 에서 property 를 선언할 때는 타입을 사용한다. (↔ function 에서 variable 을 사용할 때는 var )
  final String nickname = 'moz'; // 변경할 수 없게 final 로 선언
  int xp = 1500;

  void sayHello() {
    print("Hi my name is $name"); // this 를 사용하지 않아도 됨

    var name = 'moz';
    print("Hi my name is ${this.name}"); // 동일한 이름의 variable 이 method 내에 있을 경우는 this 로 참조 

  }
}

void main() {
  var player = Player(); // new 를 붙여도 되지만 없어도 됨
  print(player.name); // moz
  player.name = 'tiq';
  print(player.name); // tiq

  player.nickname = 'tiq'; // Error

  player.sayHello();
}

Constructor (생성자)

class Player {
  final String name; // All final variables must be initialized, but 'name' isn't.
  int xp; // Non-nullable instance field 'xp' must be initialized.

  Player(String name, int xp) { // constructor
    this.name = name; // 'name' can't be used as a setter because it's final.
    this.xp = xp;
  }
}
// late 로 처리를 하면 위에서 발생한 에러가 해결된다.
class Player {
  late final String name;
  late int xp;

  // constructor
  Player(String name, int xp) {
    this.name = name;
    this.xp = xp;
  }
}

// 훨씬 간결해진 표현
class Player {

	// late 도 제거할 수 있다.
  final String name;
  int xp;

  // constructor
  Player(this.name, this.xp); // 중복선언된 타입을 제거할 수 있다.
}

Named Constructor Parameters

class Player {
  final String name;
  int xp;
  String team;
  int age;

  // The parameter {0} can't have a value of 'null' because of its type, but the implicit default value is 'null'.
  // Positional Constructor 에서 Named Constructor 로 변경하면 에러가 발생하게 되는데 required 키워드를 붙임으로써 해결
  Player({
    required this.name,
    required this.xp,
    required this.team,
    required this.age,
  });
}

void main() {
	// 파라미터 순서와 상관없이 값을 입력할 수 있음
  var player = Player(name: 'moz', xp: 12, team: 'art', age: 13);
  var player2 = Player(team: 'tho', name: 'ben', age: 15, xp: 200);
}

Named Constructor

class Player {
  final String name;
  int xp, age;
  String team;

  Player({
    required this.name,
    required this.xp,
    required this.team,
    required this.age,
  });

  // team, xp 에 기본값을 설정한 Named Constructor with named parameters
  Player.createBluePlayer({required String name, required int age})
      : this.age = age,
        this.name = name,
        this.team = 'blue',
        this.xp = 0;

	// team, xp 에 기본값을 설정한 Named Constructor with positional parameters
  Player.createRedPlayer(String name, int age)
      : this.age = age,
        this.name = name,
        this.team = 'red',
        this.xp = 0;
}

void main() {
  var player = Player.createBluePlayer(name: 'moz', age: 13);
  var player2 = Player.createRedPlayer('ben', 15);
}

Named Constructor 를 이용한 API 연동 예시

class Player {
  final String name;
  int xp;
  String team;

  Player.fromJson(Map<String, dynamic> playerJson)
      : name = playerJson['name'],
        xp = playerJson['xp'],
        team = playerJson['team'];

  void sayHello() {
    print("Hi my name is $name");
  }
}

void main() {
  var apiData = [
    {"name": "moz", "xp": 0, "team": "tiq"},
    {"name": "tho", "xp": 0, "team": "ven"},
    {"name": "shu", "xp": 0, "team": "ber"}
  ];

  apiData.forEach((playerJson) {
    var player = Player.fromJson(playerJson);
    player.sayHello();
  });
}

Cascade Notation

class Player {
  String name;
  int xp;
  String team;

  Player({
    required this.name,
    required this.xp,
    required this.team,
  });

  void sayHello() {
    print("Hi my name is $name");
  }
}

void main() {
  var moz = Player(name: 'moz', xp: 1000, team: 'red');
  moz.name = 'tiq';
  moz.xp = 2000;
  moz.team = 'blue';
  moz.sayHello();

  // Cascade Notation
  Player(name: 'bee', xp: 1000, team: 'red')
    ..name = 'tho'
    ..xp = 3000
    ..team = 'green'
    ..sayHello();
}

Enums

// "red" 와 같이 문자열 형태로 쓰지 않아도 된다.
enum Team { red, blue }
enum XPLevel {beginner, medium, pro}

class Player {
  String name;
  XPLevel xp; // enum XPLevel 타입으로 변경되었다.
  Team team; // enum Team 타입으로 변경되었다.

  Player({
    required this.name,
    required this.xp,
    required this.team,
  });

  void sayHello() {
    print("Hi my name is $name");
  }
}

void main() {
  var moz = Player(name: 'moz', xp: XPLevel.beginner, team: Team.blue);
  moz.sayHello();
  moz
    ..name = 'tho'
    ..xp = XPLevel.pro
    ..team = Team.red
    ..sayHello();
}

Abstract Classes

  • 추상화 클래스로는 객체를 생성할 수 없다.
  • 다른 클래스들이 직접 구현해야하는 메소드들을 모아놓은 일종의 청사진 (Blueprint)
  • 특정 메소드를 구현하도록 강제한다.
abstract class Human {
  void walk();
}

class Player extends Human {

	// 구현하지 않으면 에러 발생
  void walk() {
    print('I am walking');
  }
}

Inheritance

class Human {
  final String name;

  // Human(this.name); // positional parameter
  Human({required this.name}); // named parameter
  sayHello() {
    print("Hi my name is $name");
  }
}

enum Team { red, blue }

class Player extends Human {
  final Team team;

  /// 부모객체에서 필요한 값을 초기화

  // 부모객체의 생성자가 named parameter 인 경우
  Player({required this.team, required String name}) : super(name: name);

  // 부모객체의 생성자가 positional parameter 인 경우
  // Player({required this.team, required String name}) : super(name);

  // super parameter 를 쓰는 것을 권장하고 있다.
  // Player({required this.team, required super.name});

  
  void sayHello() {
    super.sayHello();
    print('and I play for ${team}');
  }
}

void main() {
  var player = Player(team: Team.red, name: 'moz');
  player.sayHello();
}

Mixins

  • Mixin : 생성자가 없는 클래스
  • 하나의 클래스에만 사용한다면 의미가 없다.
  • 핵심은 여러 클래스에 재사용이 가능하다는 점이다.
// mixin class
mixin class Strong {
  final double stengthLevel = 1500.99;
}

mixin class QuickRunner {
  void runQuick() {
    print('ruuuuuuun!');
  }
}

mixin class Tall {
  final double height = 1.99;
}

enum Team { red, blue }

class Player with Strong, QuickRunner, Tall {
  final Team team;

  Player({required this.team});
}

class Horse with Strong, QuickRunner {}

class Kid with QuickRunner {}

void main() {}
  • #노마드코더
  • #플러터
  • #Dart