본문 바로가기

Flutter/Dart Language

[플러터 Flutter] Private, getter/setter가 무엇인가? 어떻게 사용하는가?

프라이빗 (Private)

 

Dart에서는 _name처럼 변수나 메서드의 이름 앞에 _언더스코어를 붙이면 이 변수나 메서드를 프라이빗 취급합니다.

프라이빗은 (같은 파일 내) 클래스 내부에서만 접근 가능하며
외부로부터의 직접 접근을 막아 데이터의 무결성을 유지하고
객체지향 원칙 중 하나인 캡슐화의 원칙을 지킵니다.

하지만 Dart의 프라이빗 접근 제어는 파일 수준의 접근 제한입니다.
이는 같은 파일 내에 있는 모든 코드가 프라이빗 변수와 메서드에 접근할 수 있다는 의미입니다.
그래서 같은 파일 내에서는 _로 시작하는 프라이빗 변수나 메서드에도 접근할 수 있습니다.

프라이빗 변수를 완전히 숨기려면 프라이빗 변수와 메서드를 다른 파일로 분리(리팩토링)하여 사용하는 것이 좋습니다.

 

기능 및 역할

데이터 캡슐화 (Encapsulation)

  • 클래스의 내부 상태를 외부에서 직접 접근하지 못하게 하여 데이터를 보호합니다.
  • 프라이빗 변수와 메서드는 해당 클래스 내부 또는 같은 파일 내에서만 접근할 수 있습니다.

정보 은닉 (Information Hiding)

  • 클래스 외부에서 알 필요가 없는 내부 구현 세부사항을 숨깁니다.
  • 객체의 인터페이스만 공개하고, 내부 구현은 감춥니다.

무결성 유지 (Integrity Maintenance)

  • 데이터의 무결성을 유지하기 위해 직접 접근을 제한하고, 검증된 메서드를 통해 접근하게 합니다.
  • 필요한 경우 데이터 검증을 통해 잘못된 값이 설정되지 않도록 합니다.

 

프라이빗 인스턴스 변수

class Player {
  String _name;  // 프라이빗 변수
  int _level;

  Player(this._name, this._level);
}

프라이빗 메서드

class Calculator {
  // 프라이빗 메서드
  int _add(int a, int b) {
    return a + b;
  }

  // 공개 메서드
  int calculateSum(int a, int b) {
    return _add(a, b);
  }
}

void main() {
  Calculator calculator = Calculator();
  print(calculator.calculateSum(3, 4));  // 출력: 7

  // print(calculator._add(3, 4));  // 에러: '_add' 메서드는 프라이빗이므로 접근 불가
}

 


 

게터 (Getter)

 

Getter는 인스턴스 변수의 값을 읽을 때 사용됩니다.
Dart에서는 get 키워드를 사용하여 정의합니다.

get만 사용할 경우 get앞의 반환 타입은 생략하여도 됩니다.

class MyPrivate {
  String _name; // 인스턴스 변수 앞에 _를 붙여 private으로 만듦
  int _level;

  MyPrivate(this._name, this._level);

  // Getter 메서드
  String get name => _name;  ///변수타입 생략가능 get name => _name;

  int get level => _level;  ///변수타입 생략가능 get level => _level
}

void main() {
  MyPrivate myPrivate = MyPrivate('dfasd', 1);
  print(myPrivate.name);  // 출력: dfasd
  print(myPrivate.level); // 출력: 1
}

get 을 사용하지 않았을시

get을 사용하지 않으면 프라이빗에 가려진 변수명을 볼 수 없다.

get 을 사용하였을시

get을 사용하여 선언했던 변수명이 나오는 모습.


 

세터 (Setter)

 

Setter는 인스턴스 변수의 값을 설정할 때 또는 유효성 검사, 추가로직, 데이터변환으로 사용됩니다.
Dart에서는 set 키워드를 사용하여 정의합니다.

class Player {
  String _name;
  int _level;

  Player(this._name, this._level);

  // Getter 메서드
  String get name => _name;

  // Setter 메서드
  set name(String newName) {
    _name = newName;
  }

  // Getter 메서드
  int get level => _level;

  // Setter 메서드
  set level(int newLevel) {
    if (newLevel > 1) {
      _level = newLevel;
    } else {
      print('1밑으로 내려갈 수 없습니다.');
    }
  }
}

void main() {
  Player player = Player('Alice', 10);
  print(player.name);  // 출력: Alice

  // Setter를 사용하여 값 변경
  player.name = 'Bob';
  print(player.name);  // 출력: Bob

  // Setter를 사용하여 값 변경
  player.level = 20;
  print(player.level); // 출력: 20

  // 잘못된 값 설정 시도
  player.level = -5;  // 출력: Level must be positive
  print(player.level); // 출력: 20 (값이 변경되지 않음)
}

 


프라이빗(Private), 게터(getter) / 세터(setter) 활용법

프라이빗과 게터 세터를 활용하여
level의 값은 1밑으로 내려가지 않도록 하고
name의 길이가 10자를 넘지 않도록 설정할 수 있습니다.
이를 바로 유효성 검사라고 합니다.

class MyPrivate {
  String _name;
  int _level = 1;

  MyPrivate(this._name, this._level) {
    // 생성자에서도 초기 값 검사를 수행합니다.
    if (_level < 1) {
      _level = 1;
    }
    if (_name.length > 10) {
      _name = _name.substring(0, 10);
    }
  }

  // name의 Getter
  String get name => _name;

  // name의 Setter
  set name(String newName) {
    if (newName.length <= 10) {
      _name = newName;
    } else {
      print('10글자를 넘길 수 없습니다.');
    }
  }

  // level의 Getter
  int get level => _level;

  // level의 Setter
  set level(int newLevel) {
    if (newLevel >= 1) {
      _level = newLevel;
    } else {
      print('1밑으로 내려갈 수 없습니다.');
    }
  }
}

void main() {
  MyPrivate myPrivate = MyPrivate("asdfzxcvqwrewqwerasdfe", -5);
  print(myPrivate.name); // asdfzxcvqw 까지 출력
  print(myPrivate.level); // 1 출력
  
  myPrivate.name = "asdfqwefzsdvzxcv"; // Name cannot be longer than 10 characters 출력
  myPrivate.level = -50; // Level cannot be negative 출력
}