프로그래머스 데브코스: class, getter/setter

박상하·2024년 1월 31일
0
post-thumbnail

먼저 타입스크립트에서 class를 사용하는 법을 알아보자.

Class 🎯

class Team {
 name: string;
 age: number;
 position: string;
 constructor(name:string,age:number,position:string){
   this.name=name
   this.age=age
   this.position=position
 }
  
}

자, 이렇게 하면 특별한 메소드가 없는 프로퍼티만 갖는 object를 생성할 수 있다.

const team= new Team('sangha',28,'ST')
console.log(team.position)
// ST 출력

자 그럼 Class를 조금 더 세밀하게 봐보자

constructor ? 🧐

이게뭘까?

constructor는 생성자 라는 뜻이다.
즉, 클래스 내에서 객체를 생성해 초기화하기 위한 특별한 메서드이다.
즉, 객체의 기본 상태를 저장하는 공간이다.
즉, 멤버변수들을 초기화할 수 있는 특별한 메서드이다.

만약 constructor를 사용하지 않는다면 어떻게 class를 사용할 수 있을까?

흔히 많이 클래스를 비유하는 말은 붕어빵 틀이다.

그럼 이제 constructor 없이 붕어빵을 찍어보자

class Team {
 name: string;
 age: number;
 position: string; 
}
const team = new Team()
team.name="park"
team.age=28
team.position="ST"

이런식으로 인스턴스를 생성함과 동시에 멤버변수에 대한 초기화를 진행해주어야한다.
그런데 constructor는 이러한 과정을 해결해준다.

즉, constructor는 멤버변수의 초기화를 책임져준다.

class Team{
 //이곳은 멤버변수자리
 name: string;
 age: number;
 position: string; 
   constructor(name:string,age:number,position:string){
     // 이곳에서 name이라는 멤버변수인 this.name을 매개변수 name으로 초기화시켜준다.
     // 초기화는 그냥 const a =2 와 같이 a라는 상수에 2라는 메모리 주소값을 할당시켜주는 작업이다.
   this.name=name
   this.age=age
   this.position=position
 }
  
}

그런데 이러면 외부에서 class의 멤버변수에 접근이 가능 🎯

다시 코드로 돌아와서

class Team{
 //이곳은 멤버변수자리
 name: string;
 age: number;
 position: string; 
   constructor(name:string,age:number,position:string){
     // 이곳에서 name이라는 멤버변수인 this.name을 매개변수 name으로 초기화시켜준다.
     // 초기화는 그냥 const a =2 와 같이 a라는 상수에 2라는 메모리 주소값을 할당시켜주는 작업이다.
   this.name=name
   this.age=age
   this.position=position
 }
  
}
const team = new Team("sangha",28,"ST)
team.name="updown"
console.log(team.name)
// updown

이렇게 하면 코드가 굉장히 불안하다. 언제 해당 class는 무너질지 모르는 부분이다.

그래서 우리는 접근 지정자를 통해 해당 멤버변수에 외부에서는 수정하지 못하도록 막을 수 있다.

접근지정자 🎯

public, private, protected

위 3가지는 각각, 공개 , 나만공개, 가족만공개

이렇게 정의할 수 있다. 마지막 가족만 공개는 부모자식간에서만 해당 멤버변수를 상속받고 그 외에는 멤버변수에 접근하지 못하는(private와 같음) 설정이다.

그럼 위 코드를 이렇게 수정할 수 있다.

class Team{
 //이곳은 멤버변수자리
 private _name: string;
 private _age: number;
 private _position: string; 
   constructor(name:string,age:number,position:string){
     // 이곳에서 name이라는 멤버변수인 this.name을 매개변수 name으로 초기화시켜준다.
     // 초기화는 그냥 const a =2 와 같이 a라는 상수에 2라는 메모리 주소값을 할당시켜주는 작업이다.
   this._name=name
   this._age=age
   this._position=position
 }
  
}
const team = new Team("sangha",28,"ST)
console.log(team._name)
                      //에러가 바로 발생함 
//접근을 못하게 막았으니까
                      

자 이렇게하면 class가 instance를 생성한 이후로는 해당 Instance에 멤버변수에 접근을 하지 못하게 된다.

그럼 외부에서 그 값을 어떻게 가져올순없나? 또 수정하고싶으면 어떡하지?

외부에서 값을 수정/가져오기 getter/setter 🎯

외부에서 값을 가져올 때 직접적으로 값을 가져오는 것이 아닌 class에서 setter, getter함수를 만들어 해당 메서드로 접근을 하는것이 국룰(관례)이다.

그렇게 했을 떄 장점이 뭐가있을까?

  1. 안정적인 코드(외부에서 직접적으로 해당 멤버변수를 수정하지못함)
  2. 조건문을 통해 데이터의 수정을 class 내부에서 관리할 수 있다. (캡슐화)
  3. 객체안에서 최대한 작업이 일어날 수 있음.

자 그럼 이렇게 볼 수 있다.

class Team{
 //이곳은 멤버변수자리
 private _name: string;
 private _age: number;
 private _position: string; 
   constructor(name:string,age:number,position:string){
     // 이곳에서 name이라는 멤버변수인 this.name을 매개변수 name으로 초기화시켜준다.
     // 초기화는 그냥 const a =2 와 같이 a라는 상수에 2라는 메모리 주소값을 할당시켜주는 작업이다.
   this._name=name
   this._age=age
   this._position=position
 }
  
  get playerPosition():()=>string{
    return this._position
  }
  set playerPostion(val:string){
    this._position = val
  }
}
const team = new Team("sangha",28,"ST)
console.log(team.playerPosition)
team.playerPosition("DF")
console.log(team.playerPosition)
//ST
//DF
//출력

이렇게 외부에서 직접적으로 멤버변수에 접근을 하는것이 아닌 get, set 함수를 통해 가져오는 것이다.

위 모습에서 보이는바와같이 set 프로퍼티이름 , get 프로퍼티이름
이렇게 사용하면 된다.

getter를 지양하자 ? 🧐

작성을 하면서 예전에 우테코 프리코스를 하면서 읽었던 글 (강조하셨던걸로 기억)이 생각이 났다.

getter를 사용하는 대신 객체에 메세지를 보내자

그럼 이제 그 이야기를 조금 더 이해할 수 있지 않을까? 하고 다시 해당 글을 읽어보았다.

getter지양 글

자바 빈 설계 규약에 따르면 자바 빈 클래스 설계 시,
클래스의 멤버변수의 접근제어자는 private이며,
모든 멤버변수에 대해 get메소드와 set메소드가 존재해야 한다.
get메소드는 매개변수가 없어야 하며 set메소드는 하나 이상의 매개변수가 있어야 한다.
좋은 코드를 위한 자바 메서드 네이밍 에도 간단히 설명되어 있다.

위 글에 대해 의문을 제기하며 작성된 글로 보인다.
즉 정말 모든 멤버변수에 대해 getter가 필요할까? 이말인거 같다.

또 내부의 글에는 이러한 말이 있다.

객체가 로직(행동)을 갖고 있는 형태가 아니고 메시지를 주고 받는 형태도 아니게 된다.
또한, 객체 스스로 상태값을 변경하는 것이 아니고, 외부에서 상태값을 변경할 수 있는 위험성도 생길 수 있다.

그니까 객체로 private했는데 getter를 계속사용해서 객체 그 외부에서 로직을 처리한다면
그건 객체가 객체답지 못한게 아니냐! 라는 말이었다.

그니까 getter를 통해 외부에서 로직을 처리하지 말고 내부에 메세지를 던져 그 메세지에 따른 예외사항을 처리하자는 의미인것으로 받아들여진다.

0개의 댓글

관련 채용 정보