본문 바로가기

Language Syntax/Dart

[Dart] get / set

728x90

1. 개요

Dart 에서는 getter 를 나타낼 때 get, setter 를 나타낼 때 set 이라는 키워드를 사용한다. 각각이 어떠한 때에 사용되는지 살펴보자.

2. Java 의 getter/setter

Java 에서는 private 한 속성을 외부에서 접근하거나 변경하고 싶을 때 보통 gettersetter 를 사용한다.

2.1. 예시

public class Student {
  private String id;
  public Student(String id) { this.id = id; } 
  public String getId() { return id; }
  public void setId(String id) { this.id = id; }
}
public class Main {
  public static void main(String[] args) {
    Student s1 = new Student('1000');
    Student s2 = new Student('2000');

    System.out.println(s1.getId());
    System.out.println(s2.getId());
    s1.setId('3000');
    System.out.println(s1.getId());
    System.out.println(s2.getId());
  }
}

출력결과

1000
2000
3000
2000

학생 클래스의 캡슐화된 아이디 (id) 변수를 외부에서 불러와 출력하기 위해 getId() 라는 getter 를, 외부에서 변경하기 위해 setId() 라는 setter 를 사용하였다.

물론 위와 같이 private 한 변수에 대해 getter/setter 를 동시에 두는 것은 바람직하지 않다.

3. Dart 에서는?

Dart 에서는 get 이라는 키워드를 사용하여 getter 를 나타내고 set 을 사용하여 setter 를 나타낸다. get은 곧, 매개변수가 없고 반환값만 있는 메소드에 대하여 이름만으로 메소드를 호출 가능하도록 한다. set 은 반대로 반환값이 없고 한 개의 매개변수만 존재하여, 해당 매개변수가 속성의 값을 변화시키는데 사용하는 메소드에 대하여 이름만으로 메소드 호출이 가능하다.


예시를 살펴보자.

3.1. 예시

위 Java 예시 그대로 Dart 로 구현해보자.

class Student {
  late String _id;
  Student(String id) { _id = id; }
  String get id => _id;
  set id(String id) => _id = id;
}
void main() {
  Student s1 = Student('1000');
  Student s2 = Student('2000');

  print(s1.id);
  print(s2.id);
  s1.id = '3000';
  print(s1.id);
  print(s2.id);
}

출력결과

1000
2000
3000
2000

메소드의 사용이 s1.id 형태로 이루어진다. 메소드가 마치 속성처럼 처리되는 것이다.

4. 확장 예시

getset이 비단 단순히 속성을 그대로 불러오거나 그대로 변경하는데만 쓰이진 않는다.

 

가령, 길이를 나타내는 단위를 다양하게 상호변환 가능한 프로그램을 만든다고 하자.

$ \text{mm} $, $ \text{cm} $, $ \text{m} $, $ \text{km} $ 를 변환하려면 일반적으로 다음과 같이 작성할 것이다.

class Length {
  static num mmToCm(num mm) => mm / 10;
  static num mmToM(num mm) => mm / 1000;
  static num mmToKm(num mm) => mm / 1000000;
  static num cmToMm(num cm) => cm * 10;
  static num cmToM(num cm) => cm / 100;
  static num cmToKm(num cm) => cm / 100000;
  static num mToMm(num m) => m * 1000;
  static num mToCm(num m) => m * 100;
  static num mToKm(num m) => m / 1000;
  static num kmToMm(num km) => km * 1000000;
  static num kmToCm(num km) => km * 100000;
  static num kmToM(num km) => km * 1000;
}

위 코드는 상당히 비효율적이다.
단위의 개수가 $n$ 이라고 하면 메소드의 개수는 $n(n - 1)$ 개나 필요하다.

확장성 또한 좋지 않은데, $\text{inch}$ 나 $\text{ft}$ 등의 새로운 단위를 필요로 한다면, 메소드의 개수는 점점 걷잡을 수 없이 많아질 것이다.

 

이때, getset 을 사용하면 매우 유용하다.

class Length {
  num _value = 0;

  // getters
  num get mm => m * 1000;
  num get cm => m * 100;
  num get m => _value;
  num get km => m / 1000;
  num get inch => m * 39.3700787402;
  num get ft => inch / 12;
  num get yd => ft / 3;
  num get mi => yd / 1760;

  // setters
  set mm(num v) => m = v / 1000;
  set cm(num v) => m = v / 100;
  set m(num v) => _value = v;
  set km(num v) => m = v * 1000;
  set inch(num v) => m = v / 39.3700787402;
  set ft(num v) => inch = v * 12;
  set yd(num v) => ft = v * 3;
  set mi(num v) => yd = v * 1760;
}

위 코드에서는 _value 라는 하나의 기준 값을 설정하고, m 에 대응시킨다.

그리고 모든 get 과 set 에 $\text{m}$ 와의 관계에 알맞게 계산되도록 설정하였다.

 

이는 다음과 같이 사용될 수 있다.

void main() {
  Length l = Length()..mm = 1234;
  print(l.mm);
  print(l.cm);
  print(l.m);
  print(l.km);
  print(l.inch);
  print(l.ft);
  print(l.yd);
  print(l.mi);
}

출력결과

1234.0
123.4
1.234
0.001234
48.5826771654068
4.048556430450566
1.3495188101501887
0.0007667720512216981

어떤 단위를 기준으로 값을 설정하더라도, 모든 단위로 변환될 수 있다.

728x90

'Language Syntax > Dart' 카테고리의 다른 글

[Dart] factory 예약어에 대한 고찰  (0) 2024.01.09
[Dart] 널 세이프티 (Null Safety)  (0) 2023.11.07
[Dart] 익스텐션 (Extension)  (0) 2023.10.31