[Flutter] Dart 기초2

ivor·2022년 10월 18일
0

App

목록 보기
2/3

OOP

Object Oriented Programming. 객체 지향 프로그래밍.

https://dart.dev/guides/language/language-tour#important-concepts

Class

  • class는 일종의 틀, instance는 그 틀로 찍어낸 개별 생성물.
  • class는 member를 가짐.
    • 멤버는 멤버 함수, 멤버 변수로 구성.
      • 클래스 외부에서 하나의 기능을 수행하는 함수는 Function, 클래스 내부 함수는 Method.
  • class를 사용하려면 객체를 만들어 메모리에 올려야 함. 이 과정을 인스턴스화라고 함.

class의 기본 형태와 사용법은 다음과 같다.

class Player{
  String name = 'Son';
  int age = 30;
  int backNumber = 7;
  String position = 'Forward';
  List<String> teams = ['대한민국', '토트넘']; // member variables
  
  void helloWorld(){ // method
    print('Hello World');
  }
}

void main(){
	Player son = Player();
    print(son.name);
    print(son.age);
    print(son.backNumber);
    print(son.position);
    print(son.teams);
    son.helloWorld();
}

java와 유사한 것을 확인할 수 있었다. (new를 안 써도 된다는 점 정도가 다른 것 같다.)

constructor(생성자)

인스턴스 생성하면서 동시에 멤버 변수도 초기화하고 싶다면?
생성자를 사용하면 된다. 생성자 역시 클래스 내부에 정의한다.

기본 생성자는 굳이 명시하지 않아도 자동으로 생성된다. 명시적으로 만들고 싶다면 클래스명과 같은 이름으로 선언하면 된다.
name, age 등의 멤버 변수를 미리 선언하지 않고 인스턴스를 생성하면서 동시에 선언해주고 싶다면 어떻게 할까?

class Player{
  String name;
  int age;
  int backNumber;
  String position;
  List<String> teams; // member variables
  
  // 기본 생성자
  Player(String name, int age, int backNumber, String position, List<String> teams)
  : this.name = name,
  	this.age = age,
    this.backNumber = backNumber,
    this.position = position,
    this.teams = teams;
  
  void helloWorld(){
    print("Hello World");
  } 
}

void main(){
  Player son = Player('son', 30, 7, 'Forward', ['대한민국', '토트넘']);
  print(son.name);
  print(son.age);
  print(son.backNumber);
  print(son.position);
  print(son.teams);
  son.helloWorld();
}

기본 생성자는 더 간단한 버전으로 표현할 수도 있다.

class Player{
  String name;
  int age;
  int backNumber;
  String position;
  List<String> teams; // member variables
  
  // 더 간단한 버전의 생성자.
  Player(this.name, this.age, this.backNumber, this.position, this.teams);

  void helloWorld(){
    print("Hello World");
  }
}

void main(){
  Player son = Player('son', 30, 7, 'Forward', ['대한민국', '토트넘']);
  print(son.name);
  print(son.age);
  print(son.backNumber);
  print(son.position);
  print(son.teams);
  son.helloWorld();
  
  Player kim = Player('Kim', 25, 4, 'Defender', ['대한민국', '나폴리']);
  print(kim.name);
  print(kim.age);
  print(kim.backNumber);
  print(kim.position);
  print(kim.teams);
  kim.sayHello();
}

이전에 배웠던 optional parameter 등을 활용하면 다음처럼 응용해볼 수도 있겠지.

class Player{
  String name;
  int age;
  int backNumber;
  String position;
  List<String> teamHistory; // member variables
  
  // optional parameters and default
  Player([this.name='Son', this.age=30, this.backNumber=7, this.position='Forward', this.teams=const ['대한민국', '토트넘']]);
}

void main(){
  Player son = Player();
  print(son.name);
  print(son.age);
  print(son.backNumber);
  print(son.position);
  print(son.teams);
}

이름 있는 생성자

생성자에 이름을 부여한 것이다. 기본 생성자 외에 이러한 생성자도 사용할 수 있다. (찾아보니 생성자의 종류가 많았다)

class Player{
  String name;
  int age;
  int backNumber;
  String position;
  List<String> teams; // member variables
  
  // optional parameters and default
  Player([this.name='Son', this.age=30, this.backNumber=7, this.position='Forward', this.teams=const ['대한민국', '토트넘']]);
  
  // 이름 있는 생성자
  Player.printCountry(String country, [this.name='Son', this.age=30, this.backNumber=7, this.position='Forward', this.teams=const['대한민국','토트넘']]){
    print("Player's country: ${country}");
  }
}

void main(){
  Player son = Player.printCountry('대한민국');
  print(son.name);
  print(son.age);
  print(son.backNumber);
  print(son.position);
  print(son.teams);
}

getter, setter

각각 get, set을 이용해 말 그대로 어떤 정보를 가져오거나 할당하는 것이다.

class Player{
  String name;
  int age;
  int backNumber;
  String position;
  List<String> teams; // member variables
  
  // 간단한 버전의 생성자.
  Player([this.name='Son', this.age=30, this.backNumber=7, this.position='Forward', this.teams=const ['대한민국', '토트넘']]);

  void helloWorld(){
    print("Hello World");
  }

  // 'get' #1
  String get getName{
    return this.name;
  }
  
  // 'get' #2
  int get getBackNumber => this.backNumber;
  
  
  // 'set' #1
  set setName(String name){
    this.name = name;
  }
  
  // 'set' #2
  set setBackNumber(int backNumber) => this.backNumber = backNumber;
}

void main(){
  Player player1 = Player();
  
  // getter를 통해 name, backNumber 정보 가져오기
  print(player1.getName);
  print(player1.getBackNumber);
  
  // setter를 통해 새로운 name, backNumber 할당하기
  player1.setName = 'Kim';
  player1.setBackNumber = 3;
  
  print(player1.getName);
  print(player1.getBackNumber);
}

이때 setter의 파라미터는 하나만 들어갈 수 있다고 한다. 그 이유는 main() 함수에서의 사용 예시를 보면 알 수 있다.

=>return과 같다고 들었는데 기본적으로 void로 설정된 setter에서 =>를 활용할 수 있다는 게 신기했다.

immutable programming

인스턴스의 멤버 변수에 쉽게 접근하고 수정이 가능할 경우 내부 정보가 쉽사리 변경된다는 위험성이 있다. 때문에 멤버 변수에 final을 걸어 변경 불가능하게 만드는 방법을 사용한다고 한다.

해당 방법 사용 시 초기 선언된 값으로 고정되어 추후 특정 멤버 변수값만 수정이 불가능하다. 이 경우 setter로도 변경이 불가능하다.(때문에 현대에 와서는 setter의 사용을 지양한다고도 한다.)

값을 변경하고 싶다면 변경된 값으로 새로 생성하면 된다.

class Player{
  final String name;
  int age;
  final int backNumber;
  String position;
  List<String> teamHistory; // member variables
  
  # 기본 생성자 더 간단한 버전 & optional param.
  Player([this.name='Son', this.age=30, this.backNumber=7, this.position='Forward', this.teams=const ['대한민국', '토트넘']]);
}

references

profile
BEST? BETTER!

0개의 댓글