private, protected 프로퍼티와 메서드
내부 / 외부 인터페이스
객체지향 프로그래밍에서 프로퍼티와 메서드는 두 그룹으로 분류된다
- 내부 인터페이스 - 동일한 클래스 내의 다른 메서드에선 접근할 수 있지만, 클래스 밖에선 접근할 수 없는 프로퍼티와 메서드
- 외부 인터페이스 - 클래스 밖에서도 접근 가능한 프로퍼티와 메서드
JS 객체 필드의 경우
- public : 어디서든 접근할 수 있고 외부 인터페이스를 구성
- private : 클래스 내부에서만 접근할 수 있고 내부 인터페이스를 구성할 때 쓰인다
JS 이외 다수 언어에서 클래스 자신과 자손 클래스에서만 접근을 허용하는 protected 필드를 지원한다
protected 필드는 private과 비슷하지만, 자손 클래스에서도 접근이 가능하다는 점이 다르다
자손 클래스의 필드에 접근해야하는 경우가 많기 때문에 protected 필드는 private 필드보다 조금 더 광범위하게 사용된다
프로퍼티 보호하기
class CoffeeMachine {
waterAmount = 0;
constructor(power) {
this.power = power;
alert( `전력량이 ${power}인 커피머신을 만듭니다.` );
}
}
// 커피머신 생성
let coffeeMachine = new CoffeeMachine(100);
// 물 추가
coffeeMachine.waterAmount = 200;
현재 waterAmount
와 power
프로퍼티는 public이므로 읽고 원하는 값으로 변경하기 쉬운 상태이다
waterAmount
를 protected로 바꿔서 0미만의 값으로는 설정하지 못하도록 만들어보자
_waterAmount = 0;
set waterAmount(value) {
if (value < 0) throw new Error("물의 양은 음수가 될 수 없습니다.");
this._waterAmount = value;
}
get waterAmount() {
return this._waterAmount;
}
constructor(power) {
this._power = power;
}
}
// 커피 머신 생성
let coffeeMachine = new CoffeeMachine(100);
// 물 추가
coffeeMachine.waterAmount = -10; // Error: 물의 양은 음수가 될 수 없습니다.
protected 프로퍼티 명 앞엔 밑줄 _
이 붙는다
이제 물의 양을 0 미만으로 설정하면 실패한다
읽기 전용 프로퍼티
power
프로퍼티를 읽기전용으로 만들어보자
프로퍼티를 생성할 때만 값을 할당할 수 있고, 그 이후에는 값을 절대 수정하지 말아야 할 경우가 종종 있는데, 이럴 때 읽기 전용 프로퍼티를 활용할 수 있다
읽기전용 프로퍼티를 만드려면 setter는 만들지 않고 getter만 만들어야 한다
class CoffeeMachine {
// ...
constructor(power) {
this._power = power;
}
get power() {
return this._power;
}
}
// 커피 머신 생성
let coffeeMachine = new CoffeeMachine(100);
alert(`전력량이 ${coffeeMachine.power}인 커피머신을 만듭니다.`); // 전력량이 100인 커피머신을 만듭니다.
coffeeMachine.power = 25; // Error (setter 없음)
getter와 setter 함수
위에서는 get, set 문법을 통해 getter, setter 함수를 만들었지만 대부분은 아래 같은 get.../set...
형식의 함수가 쓰인다
class CoffeeMachine {
_waterAmount = 0;
setWaterAmount(value) {
if (value < 0) throw new Error("물의 양은 음수가 될 수 없습니다.");
this._waterAmount = value;
}
getWaterAmount() {
return this._waterAmount;
}
}
new CoffeeMachine().setWaterAmount(100);
이 방식으로 함수를 선언하면 다수의 인자를 받을 수 있기 때문에 좀 더 유연하다
반면 get, set 문법을 사용하면 코드가 간결해진다는 장점이 있다
protected 필드는 상속된다
class MegaMachine extends CoffeeMachine
로 클래스를 상속받으면, 새로운 클래스의 메서드에서 this._waterAmount
나 this._power
를 사용해 프로퍼티에 접근할 수 있다
👉 protected 필드는 아래에서 보게 될 private 필드와 달리, 자연스러운 상속이 가능하다
private 프로퍼티
⚠️ 스펙에 추가된 지 얼마 안 된 문법이므로 폴리필 구현이 필요하다
private 프로퍼티와 메서드는 제안(proposal) 목록에 등재된 문법으로, 명세서에 등재되기 직전의 상태이다
private 프로퍼티와 메서드는 #
으로 시작한다
#
으로 시작하면 클래스 안에서만 접근 가능하다
물 용량 한도를 나타내는 private 프로퍼티 #waterLimit
과 남아있는 물의 양을 확인해주는 private 메서드 #checkWater
를 구현해보자
class CoffeeMachine {
#waterLimit = 200;
#checkWater(value) {
if (value < 0) throw new Error("물의 양은 음수가 될 수 없습니다.");
if (value > this.#waterLimit) throw new Error("물이 용량을 초과합니다.");
}
}
let coffeeMachine = new CoffeeMachine();
// 클래스 외부에서 private에 접근할 수 없음
coffeeMachine.#checkWater(); // Error
coffeeMachine.#waterLimit = 1000; // Error
#
은 JS에서 지원하는 문법으로, private 필드를 의미한다
private 필드는 클래스 외부나 자손 클래스에서 접근 불가능하다
private 필드는 public 필드와 상충하지 않는다
private 프로퍼티 #waterAmount
와 public 프로퍼티 waterAmount
를 동시에 가질 수 있다
#waterAmount
의 접근자 waterAmount
를 만들어보자면
class CoffeeMachine {
#waterAmount = 0;
get waterAmount() {
return this.#waterAmount;
}
set waterAmount(value) {
if (value < 0) throw new Error("물의 양은 음수가 될 수 없습니다.");
this.#waterAmount = value;
}
}
let machine = new CoffeeMachine();
machine.waterAmount = 100;
alert(machine.#waterAmount); // Error
protected 필드와 달리, private 필드는 언어 자체에 의해 강제된다는 점이 장점이다
요약
객체 지향 프로그래밍에선 내부 / 외부 인터페이스를 구분하는 것을 캡슐화(encapsulation)라는 용어를 사용해 설명한다
캡슐화❔
내부 인터페이스를 엄격하게 구분하면, 클래스 개발자들은 사용자에게 알리지 않고도 자유롭게 내부 프로퍼티와 메서드들을 수정할 수 있다
내부 인터페이스가 엄격히 구분된 클래스를 만지고 있다면, 그 어떤 외부 코드도 내부 private 메서드에 의존하고 있지 않기 때문에 private 메서드의 이름을 안전하게 바꿀 수 있고, 매개변수를 변경하거나 없앨 수도 있다
사용자 입장에서는 새로운 법전이 출시되면서 내부 정비가 전면적으로 이뤄졌더라도 외부 인터페이스만 똑같다면 업그레이드가 용이하다는 장점이 있다
복잡성 은닉
구현 세부사항이 숨겨져 있으면 간단하고 편리해지며 외부 인터페이스에 대한 설명도 문서화하기 쉬워진다
내부 인터페이스를 숨기려면 protected 나 private 프로퍼티를 사용하면 된다
- protected 필드는
_
로 시작하는 것이 관습처럼 사용된다. 개발자는 protected 프로퍼티가 정의된 클래스와 해당 클래스를 상속받는 클래스에서만_
가 붙은 필드에 접근해야 한다 - private 필드는
#
로 시작하며, JS에서 지원하는 문법이고#
로 시작하는 필드는 해당 필드가 정의된 클래스 내부에서만 접근 가능하다
모든 브라우저에서 private 필드를 지원하지는 않지만 폴리필을 구현하여 사용할 수 있다
Author And Source
이 문제에 관하여(private, protected 프로퍼티와 메서드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@100pearlcent/private-protected-프로퍼티와-메서드저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)