본문 바로가기

IT 일기/Flutter!

Dart를 빠르게 알아보자 - class! #1

728x90

1. Class!

class Player {
  String name = "gyugyu";
  int power = 130;
  final String neverChange = "man";

  void sayHello() {
    print("Hi my name is $name and i'm $neverChange");
  }
}

void main() {
  var player = Player();
  print(player.name);
  player.name = "hun";
  print(player.name);
  player.sayHello();
}

class [class 명]의 형식으로 기본 class를 생성할 수 있다. class의 property들은 타입을 명시해야 한다. (var를 사용할 수 없는건 아니지만 타입 명시를 권고함) 또한 method도 class 내부에서 작성한다. this를 사용할 수 있지만 위와 마찬가지로 권고하지 않는다.

만약 클래스 내부 property 혹은 method를 사용하고 싶다면 var player = Player()와 같이 객체를 생성하고 player.name과 같이 사용할 수 있다. 하지만 특정 property에 접근하지 못하게 하고자 한다면 변수명 앞에 final을 붙인다.

 

2. Constructor!

class Player {
  var name = "gyugyu";
  int power = 130;
  final String neverChange;

  Player(this.name, this.power, this.neverChange);

  void sayHello() {
    print("Hi my name is $name and i'm $neverChange");
  }
}

void main() {
  var player = Player("gyu", 10, "man");
  var player1 = Player("hyun", 20, "girl");
  print(player.name);
  print(player1.name);
}

위와 같이 간단한 방법으로 constructor를 만들 수 있다. 중요한건 위치다. Player(this.name, this.power, this.neverChange)에서 해당 constructor를 부를때 첫번째 인자를 name에 두번째 인자를 power에 세번째 인자를 neverChange에 넣으라는 의미이다.

=> 하지만 이 방식은 위치가 고정적이기 때문에 위치를 기억해야 한다는 단점이 있음.

 

3. Named Constructor Parameters!

class Player {
  var name = "gyugyu";
  int power = 130;
  final String neverChange;

  Player({required this.name, required this.power, required this.neverChange});

  void sayHello() {
    print("Hi my name is $name and i'm $neverChange");
  }
}

void main() {
  var player = Player(name: 'gyu', neverChange: 'man', power: 12);
  var player1 = Player(power: 11, neverChange: 'girl', name: "hyun");
  print(player.name);
  print(player1.name);
}

함수 부분에서 사용한 named parameter를 class의 constructor에도 적용할 수 있다. main함수 부분의 객체 생성에서 보면 인자의 순서를 맞추지 않아도 정상적으로 작동되는 것을 알 수 있다. 

주의해야 할 점은 constructor의 인자 부분을 {}로 묶어줘야 한다는 것과 각 인자들이 null이 될 수도 있으니 null에 대한 처리를 해줘야 한다는 것이다.

간단하게 required를 추가해주거나 혹은 default value를 설정해줘도 된다.

 

4. Named Constructor!

class Player {
  var name = "gyugyu";
  int power = 130;
  final String neverChange;

  Player({required this.name, required this.power, required this.neverChange});

  Player.createGyuFamily({required String name, required int power})
      : this.name = name,
        this.power = power,
        this.neverChange = 'man';

  void sayHello() {
    print("Hi my name is $name and i'm $neverChange");
  }
}

void main() {
  var player = Player.createGyuFamily(name: "gyu", power: 11);
  var player1 = Player(power: 11, neverChange: 'girl', name: "hyun");
  print(player.name);
  print(player1.name);
}

위 constructor들을 만들며 의문이 생겼다. 왜 여러개의 constructor를 만들 수 없지? 그리고 위의 예제가 그 방법이다. Player.(Named constructor)(인자,인자, ...) : (property 초기화) 의 모습으로 구성된다.

간딴하다! 

읽다보면 왜 위에서 this 쓰지 말라고 하고 쓰지..? 라는 의문이 생길 수 있는데 그 이유는 인자의 이름이 property의 이름과 같아서 사용하는 것이다. 다르면 안써도 됨! 같으면 써야됨...

 

5. Cascade Notation!

class Player {
  var name = "gyugyu";
  int power = 130;
  final String neverChange;

  Player({required this.name, required this.power, required this.neverChange});

  Player.createGyuFamily({required String name, required int power})
      : this.name = name,
        this.power = power,
        this.neverChange = 'man';
  Player.clone(Player player)
      : this.name = player.name,
        this.power = player.power,
        this.neverChange = player.neverChange;
  void sayHello() {
    print("Hi my name is $name and i'm $neverChange");
  }
}

void main() {
  var player = Player.createGyuFamily(name: "gyu", power: 11);
  var newPlayer = player
    ..name = 'new'
    ..power = 123;
  var newPlayer2 = Player.clone(player)..name = 'new3';
  print(player.name);
  print(newPlayer.name);
  print(newPlayer2.name);
}

손쉽게 property를 바꾸는 방법이다. main함수에서 ..을 통해 새로 생성된 객체의 property 값을 바꿨다. 근데 사전에 생성해 둔 객체를 단순히 대입하면 얕은 복사가 일어나 변경이 두 변수에 같이 적용되는 문제가 있다.

이를 해결하기 위해 named constructor로 clone을 생성했고 이를 이용해 값을 복사하고 사용하면 위의 문제는 발생하지 않는다.

 

6. Enum!

enum House { gyu, hyun }

class Player {
  House name;
  int power = 130;
  final String neverChange;

  Player({required this.name, required this.power, required this.neverChange});

  Player.createGyuFamily({required House name, required int power})
      : this.name = name,
        this.power = power,
        this.neverChange = 'man';
  Player.clone(Player player)
      : this.name = player.name,
        this.power = player.power,
        this.neverChange = player.neverChange;
  void sayHello() {
    print("Hi my name is $name and i'm $neverChange");
  }
}

void main() {
  var player = Player.createGyuFamily(name: House.gyu, power: 11);
  print(player.name.name);
}

Enum은 오타를 방지하기 위해 사용된다. 코드 제일 상위처럼 특정 값을 enum에 등록하고 사용한다. 그러면 main함수에서 player 객체를 생성하는 과정에서 gyu를 오타내지 않고 사용할 수 있다. 값을 출력할때는 .name을 사용하고 index를 알고 싶을 때는 .index를 사용한다. 

728x90