TIL

[TIL] 2021년 12월 27일

건브로 2021. 12. 27. 22:21

1. 오늘 배운 것

 

class

접근 제어자(private, public, protected)

이중 초기화 막기

readonly

super()

override

getter

setter

static

추상 클래스

싱글톤 패턴

 

2. class에 대한 공부

class 내부의 필드에 있는 변수들은 속성이라고 한다.

 

//TypeScript
//일반적으로 쓰이는 class
class Animal {
    kind: string;
    habitat: string;
    constructor(kind: string, habitat: string){
        this.kind = kind;
        this.habitat = habitat;
    }
    printIntroduction(){
        console.log('이 동물의 종류는 ' + this.kind + '입니다.');
        console.log('그리고 서식지는 ' + this.habitat +'입니다.');
    }
}

const cat = new Animal('mammalia', 'city');
//1. 생성자를 사용하고나서 객체의 함수 사용시
cat.printIntroduction();

//이 동물의 종류는 mammalia입니다.
//그리고 서식지는 city입니다.

//2. 객체의 속성을 인위적으로 바꿀 때
cat.kind = "feline";
cat.printIntroduction();

//이 동물의 종류는 feline입니다.
//그리고 서식지는 city입니다.

 

여기까지는 일반 클래스인데, 객체의 속성을 내 맘대로 바꿀 수가 있다.

이러면 팀 프로젝트 할 때, 일관성이 깨질 수도 있다.

 

//TypeScript
//접근 제어자, 이중 초기화를 막기, 상속, override(재정의)가 녹아있는 class
class Animal {
    constructor(private kind: string, public habitat: string){
        this.kind = kind;
        this.habitat = habitat;
    }
    printIntroduction(){
        console.log('이 동물의 종류는 ' + this.kind + '입니다.');
        console.log('그리고 서식지는 ' + this.habitat +'입니다.');
    }
}

class Cat extends Animal {
    constructor(kind: string, habitat: string, public kindType: string){
        //super()는 자식이 부모의 속성을 상속하고자 할 때 쓰는 것
    	super(kind, habitat);
    }
    //override
    printIntroduction(){
        //오류 발생!! this.kind를 접근 할 수 없다.
        console.log('이 동물의 종류는 ' + this.kind + '입니다.');
        console.log('그리고 서식지는 ' + this.habitat +'입니다.');
        console.log('이 동물의 세부적인 종류는' + this.kindType + '입니다.' );
    }
}

const cat = new Animal('mammalia', 'city');
//1. 생성자를 사용하고나서 객체의 함수 사용시
cat.printIntroduction();

//이 동물의 종류는 mammalia입니다.
//그리고 서식지는 city입니다.

//2. 객체의 속성을 인위적으로 바꿀 때 => kind 속성이 private이기때문에 이제 접근 못한다.
//오류는 걸려도 실행은 된다. 다만, 컴파일러는 감지하고 고치라고 할뿐
cat.kind = "feline";
cat.printIntroduction();

//이 동물의 종류는 mammalia입니다.
//그리고 서식지는 city입니다.

 

접근제어자에는 protected도 존재하는데, 이것을 사용한다면?

위의 코드에서 발생한 첫 번째 오류는 사라진다.

 

그리고 static 키워드를 사용하면 클래스와는 멀어진다.

그냥 일반 함수나 변수를 사용하는 느낌으로 바뀐다.

 

 

//TypeScript
//readonly, getter, setter, static 개념이 녹아 있는 class
class Animal {
    static readonly livingPlanet = 'earth';
    constructor(protected kind: string, public habitat: string){
        this.kind = kind;
        this.habitat = habitat;
    }
    
    get currentKind(){
        if(this.kind){
            return this.kind;
        }
        throw new Error('There is no kind');
    }
    
    set currentKind(kind: string){
        if(!kind){
            throw new Error('There is no parameter');   
        }
        this.kind = kind;
    }
    
    printIntroduction(){
        console.log('이 동물의 종류는 ' + this.kind + '입니다.');
        console.log('그리고 서식지는 ' + this.habitat +'입니다.');
    }
    
    static printLivingPlanet(){
        console.log("우리가 살고 있는 행성: " + this.livingPlanet);
    }
}

class Cat extends Animal {
    constructor(kind: string, habitat: string, public kindType: string){
    	super(kind, habitat);
    }
    //override
    printIntroduction(){
    	//오류 해제!
        console.log('이 동물의 종류는 ' + this.kind + '입니다.');
        console.log('그리고 서식지는 ' + this.habitat +'입니다.');
        console.log('이 동물의 세부적인 종류는' + this.kindType + '입니다.' );
    }
}

const cat = new Cat('mammalia', 'city', '고양이과');
console.log(cat.currentKind);
cat.currentKind = '포유류';
console.log("현재 동물의 종류: " + cat.currentKind);
console.log(Cat.livingPlanet);
Cat.printLivingPlanet();

 

 

추상 클래스를 사용하려면, 먼저 추상 메소드를 사용해야한다.

 

1개 이상의 추상 메소드가 있다면, 추상 클래스로 사용할 수 있다.

 

내일 공부할 인터페이스와는 조금 차이가 있다.

 

인터페이스는 내의 속성들은 선언만 되었지, 값이 없다.

근데, 추상 클래스는 선언만 되어 있는 메소드가 있을 수도 있고,

선언과 할당 모두 되어있는 메소드가 있을 수 있다.

 

그러니 두 개념은 엄연히 다르다는 것을 알 수 있다.

 

 

//TypeScript
//추상 클래스 개념이 녹아 있는 class
//abstract 키워드 사용
abstract class Animal {
    static readonly livingPlanet = 'earth';
    constructor(protected kind: string, public habitat: string){
        this.kind = kind;
        this.habitat = habitat;
    }
    
    get currentKind(){
        if(this.kind){
            return this.kind;
        }
        throw new Error('There is no kind');
    }
    
    set currentKind(kind: string){
        if(!kind){
            throw new Error('There is no parameter');   
        }
        this.kind = kind;
    }
    //abstract 키워드를 써야하며, 함수같은 경우는 이렇게 설정하자
    abstract printIntroduction(): void;
    
    static printLivingPlanet(){
        console.log("우리가 살고 있는 행성: " + this.livingPlanet);
    }
}

class Cat extends Animal {
    constructor(kind: string, habitat: string, public kindType: string){
    	super(kind, habitat);
    }
    //override
    printIntroduction(){
    	//오류 해제!
        console.log('이 동물의 종류는 ' + this.kind + '입니다.');
        console.log('그리고 서식지는 ' + this.habitat +'입니다.');
        console.log('이 동물의 세부적인 종류는' + this.kindType + '입니다.' );
    }
}

const cat = new Cat('mammalia', 'city', '고양이과');
cat.printIntroduction();

 

//TypeScript
//싱글톤 패턴의 개념이 녹아 있는 class

abstract class Animal {
  static readonly livingPlanet = "earth";
  constructor(protected kind: string, public habitat: string) {
    this.kind = kind;
    this.habitat = habitat;
  }

  get currentKind() {
    if (this.kind) {
      return this.kind;
    }
    throw new Error("There is no kind");
  }

  set currentKind(kind: string) {
    if (!kind) {
      throw new Error("There is no parameter");
    }
    this.kind = kind;
  }

  abstract printIntroduction(): void;

  static printLivingPlanet() {
    console.log("우리가 살고 있는 행성: " + this.livingPlanet);
  }
}

class Cat extends Animal {
  //꼭 이 클래스 타입에 대해서 외부에서 접근할 수 없지만, 생성자 없이도 접근 가능한 인스턴스 속성이 있어야한다.
  private static instance: Cat;
  //private 키워드 사용함으로써 이제 인스턴스는 하나로 고정이기 때문에 constructor은 접근 불가능하다.
  private constructor(kind: string, habitat: string, public kindType: string) {
    super(kind, habitat);
  }
  //외부에서 하나의 객체만 만드는 핵심적인 함수
  static getInstance() {
    if (Cat.instance) {
      return this.instance;
    }
    return new Cat("포유류", "도시", "고양이과");
  }

  //override
  printIntroduction() {
    console.log("이 동물의 종류는 " + this.kind + "입니다.");
    console.log("그리고 서식지는 " + this.habitat + "입니다.");
    console.log("이 동물의 세부적인 종류는" + this.kindType + "입니다.");
  }
}
const cat = Cat.getInstance();
cat.printIntroduction();
//44번줄에 대한 속성 값이 49번줄부터 51번줄 내용에 삽입되어 출력된다.

 

 

3. 느낀점

예전에 공부하던 class 개념을 다시 깨워주었다.

근데 class를 공부하다보면, this라는 개념과 prototype과 연관이 있을 수 밖에 없다.

 

한 번 공부하고, 글을 써야겠다.

 

그리고 typescript의 접근 제어자와 자바스크립트 접근 제어자는 생김세가 다르다.

처음엔 typescript의 접근 제어자를 봤을 때는 아 이거 자바스크립트에도 있었나 생각했다.

근데, 아니었다니...

'TIL' 카테고리의 다른 글

[TIL] 2022년 01월 6일  (0) 2022.01.06
[TIL] 2021년 12월 28일  (0) 2021.12.28
[TIL] 2021년 12월 23일  (0) 2021.12.23
[TIL] 2021년 12월 21일  (0) 2021.12.21
[TIL] 2021년 12월 20일  (0) 2021.12.20