개발노트

5. [TypeScript] Class 로 객체 및 데이터형 만들기 본문

웹 개발/TypeScript

5. [TypeScript] Class 로 객체 및 데이터형 만들기

mroh1226 2023. 8. 4. 16:32
반응형

class (클래스)

class MyClass {
  private name: string;
  private age: number;

  constructor(name: string, age: number) {
    // 클래스의 인스턴스 변수에 값을 할당
    this.name = name;
    this.age = age;
    
    // 생성자에서 추가적인 초기화 로직 수행 가능
    console.log(`${this.name} 객체가 생성되었습니다.`);
  }

  // 클래스의 메서드
  sayHello() {
    console.log(`안녕하세요, 저는 ${this.name}이고, ${this.age}살입니다.`);
  }
}

// 클래스의 객체 생성
const myObject = new MyClass("Alice", 30);
myObject.sayHello(); // 출력: 안녕하세요, 저는 Alice이고, 30살입니다.
  • class 안에 있는 constructor를 이용하여 생성자를 선언해줍니다.
  • 중괄호 () 안에는 객체 생성에 필요한 매개변수들을 넣어줍니다.
  • 대괄호 {} 안에는 매개변수의 값을 전달하거나 다른 값으로 초기화 할 수 있는 소스를 작성합니다.
  • 객체 생성은 객체지향언어인 C#과 비슷하게 new를 사용하여 생성합니다.

abstract class (추상 클래스)

abstract class User { //추상 Class
  constructor(
    protected firstName: string,
    protected lastName: string,
    public nickName: string
  ) {}
  getFullName() {
    return `${this.lastName + this.firstName}`;
  }
  abstract getNickName(): void; //추상 메소드 상속받는 Class에서 재정의가 요구됨
}

class Player extends User {
  //Player Class가 추상 Class인 User를 상속받음
  getNickName() {
    //추상 메소드를 재정의함
    return `${this.nickName}`;
  }
}
const player1 = new Player("길동", "홍", "닉네임"); //생성자로 Player 객체 생성
player1.nickName = "의적"; //public nickName이기 때문에 접근가능
console.log(player1.getFullName());

설명.

  1. abstract class User { ... }:
    User 클래스는 추상 클래스로 선언되었습니다.
    firstName, lastName, nickName 세 개의 멤버 변수를 가지고 있습니다.
    constructor(...)에서 세 개의 멤버 변수를 초기화합니다.

  2. constructor(...):
    생성자를 사용하여 객체를 생성할 때, firstName, lastName, nickName을 전달받아 해당 인스턴스 변수들을 초기화합니다.
    protected 접근 제어자를 사용하여 firstName, lastName는 자식 클래스에서 접근할 수 있도록 하고, public 접근 제어자를 사용하여 nickName은 외부에서 직접 접근 가능하도록 합니다.

  3. getFullName():
    이 메서드는 firstName과 lastName을 합쳐서 전체 이름을 반환하는 일반 메서드입니다.

  4. abstract getNickName(): void;:
    getNickName() 메서드는 추상 메서드로 선언되었습니다.
    추상 메서드는 구현 내용이 없으며, 하위 클래스에서 반드시 구현되어야 합니다.

  5. class Player extends User { ... }:
    Player 클래스는 User 클래스를 상속받습니다.

  6. getNickName():
    Player 클래스에서 getNickName() 메서드를 재정의하여 자신만의 구현을 제공합니다.

  7. const player1 = new Player("길동", "홍", "닉네임");:
    Player 클래스의 인스턴스 player1을 생성합니다. 이때, Player 클래스의 생성자가 User 클래스의 생성자를 호출하여 상속된 인스턴스 변수들을 초기화합니다.

  8. player1.nickName = "의적";:
    nickName 변수를 변경하는 코드로, nickName은 public 접근 제어자로 선언되었기 때문에 외부에서 직접 접근이 가능합니다.

  9. console.log(player1.getFullName());:
    getFullName() 메서드를 호출하여 플레이어의 전체 이름을 출력합니다. lastName과 firstName이 합쳐져서 "홍길동"이 출력됩니다.

  10. console.log(player1.getNickName());:
    getNickName() 메서드를 호출하여 플레이어의 닉네임을 출력합니다. getNickName() 메서드는 Player 클래스에서 재정의된 메서드이므로, "의적"이 출력됩니다.

콘솔 출력

 


class를 데이터형으로 사용하기(with Index Signature)

 

Index Signature

type MyObjectType = {
  [keyType: keyValueType]: valueType;
};
  • keyType: 이 부분에 작성된 타입은 객체의 key로 사용될 수 있는 타입입니다. 주로 string 또는 number 타입을 사용합니다. 예를 들어, string으로 설정하면 객체의 key는 문자열이어야 합니다. 마찬가지로 number로 설정하면 객체의 key는 숫자여야 합니다.
  • keyValueType: 이 부분에 작성된 타입은 객체의 key에 해당하는 값(value)의 타입을 의미합니다. 이 부분은 key와 연결된 값의 타입을 지정합니다.
  • valueType: 이 부분에 작성된 타입은 객체의 값(value)의 타입을 의미합니다. 이는 keyValueType와 같은 의미를 가집니다. TypeScript에서는 두 가지 표현 방법이 동일한 의미를 가집니다.

예를 들어, 다음과 같은 인덱스 시그니처를 사용하는 타입을 정의하면, 객체는 string 타입의 key와 해당하는 number 타입의 값을 가질 수 있습니다:

type MyNumberDictionary = {
  [key: string]: number;
};

const myDict: MyNumberDictionary = {
  apple: 1,
  banana: 2,
  cherry: 3,
};

위 예제에서 MyNumberDictionary 타입은 객체의 key가 string이고, 값이 number인 형태의 딕셔너리를 나타냅니다. myDict 객체는 이 타입을 따르기 때문에, "apple", "banana", "cherry"와 각각에 해당하는 1, 2, 3이라는 값을 가집니다.

 

예시.

type MyIndexSignatue = {
  [keyType: string]: string; //Index Signature
};

class Word {
  //데이터 형식처럼 사용할 Word class 생성
  constructor(public wordName: string, public means: string) {}
}

class Dict {
  private indexSign: MyIndexSignatue; //MyindexSignature를 Entity로 갖는 Dict Class 선언
  constructor() {
    this.indexSign = {}; //초기화
  }
  //객체 메소드 구현
  add(word: Word) { //add는 class Word를 매개변수로받음
    if (this.indexSign[word.wordName] === undefined) {
      //indexSign[word.wordName] 는 means를 말함 즉,value가 정의되지않았다면
      this.indexSign[word.wordName] = word.means;
      //means에 매개변수로 받은 word.means 값을 넣음
    }
    //이미 value가 정의되어있는 Word Key값 일 경우 
    //if문을 타지않기 때문에 아무일도 일어나지않음(Dict에 추가되지않음)
  }
  def(wordName: string) {  //def는 string을 매개변수로 받음
    return this.indexSign[wordName];
  }
}

const ant = new Word("ant", "개미");
const ant2 = new Word("ant", "개미");
const ant3 = new Word("ant3", "개미");
const hello = new Word("hello", "안녕하세요");
const hi = new Word("hi", "안녕");
const dict = new Dict();
dict.add(ant);
dict.add(ant2);
dict.add(ant3);
dict.add(hello);
dict.add(hi);
console.log(dict.def("ant"));
console.log(dict.def("ant2"));
console.log(dict.def("ant3"));
console.log(dict.def("hello"));
console.log(dict.def("hi"));
console.log(dict);

 

콘솔 출력값

 

메소드 확장

import "./style.css";

type WordsIndexSign = {
  [key: string]: string;
};
class Word {
  constructor(public wordName: string, public means: string) {}
}

class Dict {
  private words: WordsIndexSign;
  constructor() {
    this.words = {};
  }
  add(word: Word) {
    if (this.words[word.wordName] === undefined) {
      this.words[word.wordName] = word.means;
    }
  }
  get(wordName: string) {
    return this.words[wordName];
  }
  delete(wordName: string) {
    delete this.words[wordName];
  }
  update(word: Word) {
    if (this.words[word.wordName] === undefined) return;
    this.words[word.wordName] = word.means;
  }
  showAll() {
    console.log(this.words);
  }

  count() {
    return Object.keys(this.words).length;
  }

  upsert(word: Word) {
    this.words[word.wordName] = word.means;
  }

  exists(wordName: string) {
    return this.words.hasOwnProperty(wordName);
  }

  bulk_Add(words: Word[]) {
    words.forEach((word) => {
      if (!this.words[word.wordName]) {
        this.words[word.wordName] = word.means;
      }
    });
  }

  bulk_Delete(means: string[]) {
    means.forEach((mean) => {
      const wordName = this.findWordNameByMean(mean);
      if (wordName) {
        delete this.words[wordName];
      }
    });
  }

  private findWordNameByMean(means: string): string | undefined {
    return Object.keys(this.words).find(
      (wordName) => this.words[wordName] === means
    );
  }
}

const dict = new Dict();
const word1 = new Word("one", "하나");
const word2 = new Word("two", "둘");
const word3 = new Word("apple", "사과");
const word4 = new Word("banana", "바나나");
const word5 = new Word("tomato", "토마토");
dict.add(word1);
dict.add(word2);
dict.add(word3);
dict.add(word4);
dict.add(word5);
dict.showAll();
dict.delete("tomato");
console.log(dict.exists("banana"));
dict.bulk_Add([
  { wordName: "kimchi", means: "김치~" },
  { wordName: "no", means: "아니요" }
]);
dict.showAll();
dict.bulk_Delete(["사과", "바나나"]);
dict.showAll();
console.log(dict.count());
반응형
Comments