06.TS Class
Updated:
TS class
1.What is class ?
-
object 를 만드는 blueprint (설계도)
-
클래스 이전에 object 를 만드는 기본적인 방법은 function
-
JS 에서도 class 는 ES6 부터 사용 가능
-
OOP 을 위한 초석
-
JS 에서는 클래스도 사용자가 만드는 타입의 하나임
2.class 개요
// class 의 이름의 시작은 보통 대문자로 시작.
class Person {
name;
constructor(name: string) {
this.name = name;
}
}
const p1 = new Person("Jacob");
console.log(p1);
-
class 키워드를 이용하여 클래스를 만들 수 있습니다.
-
class 이름은 보통 대문자를 이용합니다.
-
new 를 이용하여 class 를 통해 object 를 만들 수 있습니다.
-
constructor 를 이용하여 obejct 를 생성하면서 값을 전달할 수 있습니다.
-
this 를 이용해서 만들어진 object 를 가리킬 수 있습니다.
-
JS 로 컴파일되면 es5 의 경우 function 으로 변경됩니다.
3.constructor & initialize
class Person {
name: string = "Jacob"; // 직접 Jacob 이라는 string 을 알려줘야 class 에서 initialize 된 것을 알기 때문에 error 가 발생하지 않음
age!: number; // age 타입의 값을 initialize 해줘야 error 가 생기지 않음
// class 에서 ! 를 사용하면, 일단은 초기화 하지 않고 나중에 해주겠다는 의미 일종의 pass 근데, 나중에 값을 지정하지 않으면 complie 시 error 발생 (! 쓸때는 주의해서 써야함.)
}
const p1 = new Person();
console.log(p1);
p1.age = 80; // class 에서 ! 사용한것을 지정 해주기 위해 작성된 코드
console.log(p1.age);
- constructor 를 사용해서 type 지정해주는 경우
class Person {
name: string = "Jacob";
age: number;
constructor(age?: number) {
if (age === undefined) {
this.age = 20;
} else {
this.age = age;
}
}
const p1 = new Person(80);
const p2 = new Person()
console.log(p1);
p1.age = 80; // class 에서 ! 사용한것을 지정 해주기 위해 작성된 코드
console.log(p1.age);
-
생성자 함수가 없으면, 디폴트 생성자가 불립니다
-
프로그래머가 만든 생성자가 하나라도 있으면, 디폴트 생성자는 사라집니다.
-
strict 모드에서 프로퍼티를 선언하는 곳 또는 생성자에서 값을 할당해야 합니다.
-
프로퍼티를 선언하는 곳 또는 생성자에서 값을 할당하지 않는 경우에는 ! 를 붙여서 위험을 표시 합니다.
-
클래스의 프로퍼티가 정의되어 있지만, 값을 대입하지 않으면 undefined 입니다.
-
생성자에는 async 를 설정할 수 없습니다.
4.접근 제어자 (Access Modifiers)
class Person { // public 은 전역으로 호출해서 사용할 수 있음
public name: string = "Jacob";
private _age!: number; // 공식적이지는 않지만, private 을 사용할때 _ underbar 를 사용해서 호출이 안된다는것을 암묵적으로 표시해서 사용하고 있음
private constructor(age?: number) { // private 은 constructor 안에서만 호출하는것
if (age === undefined) {
this.age = 20;
} else {
this.age = age;
}
}
public async init() { }
}
const p1: Person = new Person(80); // private 이기 때문에 Person 을 호출할 수 없음
console.log(p1.);
-
접근 제어자에는 public, private, protected 가 있습니다.
-
따로 설정하지 않으면 public 입니다.
-
클래스 내부의 모든 곳에 (생성자, 프로퍼티, 매서드) 설정이 가능합니다
-
private 으로 설정하면 클래스 외부에서 접근할 수 없습니다.
-
JS 에서는 private 을 지원하지 않아 오랜동안 프로퍼티나 메서드 이름 앞에 _ (underbar) 를 붙여서 사용해왔습니다. (습관인거지, 특별히 기준은 아니다, 즉 안써도 된다는것..)
-
protected 는 private 인데 상속 받으면 접근 할 수 있는 제어자 입니다.
5.initialization in constructor parameters
- Capter 4 의 코드를 줄여서 다음과 같이 작성 할 수 있습니다.
class Person {
public constructor(public name: string, private age: number) {}
}
const p1: Person = new Person("Jacob", 80);
console.log(p1);
6.getter & setter
class Person {
public constructor(private _name: string, private age: number) {}
get name() {
// return 을 해줘야함
// console.log("get");
return this._name + " Ko";
}
set name(n: string) {
// 뭔가 인자를 받아서 넣어 줘야 하는것
console.log("set");
this._name = n;
}
}
const p1: Person = new Person("Jacob", 80);
console.log(p1.name); // 이와 같이 name 을 꺼내 오는 것을 get, 그것을 하는 함수를 getter
p1.name = "John"; // name 에 뭔가 새로운것을 다시 입력하는 것을 set, 그것을 하는 함수를 setter
console.log(p1.name); // 이와 같이 name 을 꺼내 오는 것을 get, 그것을 하는 함수를 getter
7.readonly properties
class Person {
public readonly name: string = "Jacob"; // class 밖에서 read 만 할 수 있음
private readonly country: string;
public constructor(private _name: string, private age: number) {
this.country = "Korea";
}
hello() {
this.country = "USA"; // readonly 가 있기 때문에 값을 바꾸려고 할때 error 가 발생됨
}
}
const p1: Person = new Person("Jacob", 80);
console.log(p1.name); // get
p1.name = "John"; // readonly 를 사용하면 set 을 사용한 값을 변경 할 수 없다
console.log(p1.name);
// readonly 는 초기화 되는 영역에서만 값을 바꿀 수 있으며, 다른 영역에서는 바꿀수 없음
// public 이 있어도 readonly 가 있으면 영역 밖에서 값을 바꿀 수 없음
8.index signatures in class
class Students {
// 값을 동적으로 처리하기 위해 index signature 를 사용
[index: string]: "male" | "female";
}
const a = new Students();
a.Jacob = "male";
a.John = "male";
console.log(a);
const b = new Students();
b.Emma = "female";
b.Tom = "male";
b.Sharah = "female";
console.log(b);
// 원래 class 에서 선언을 하면, property 를 항상 initialize 해줬어야 했는데, index signature 는 초기값을 따로 설정 안해줘도 동작함..
// class 에서 index signature 선언한 후, 다른 값을 넣으려면 male, female 에 양식에 맞는 type 으로만 가능하다
9.static properties & methods
class Person {
public static City = "Seoul";
public static hello() {
console.log("안녕하세요", Person.City);
}
public static change() {
Person.City = "Busan";
}
}
const p1 = new Person();
// p1.hello(); // 기존의 호출 방식 class -> 변수 p1 -> 변수.함수() 메서드 사용
Person.hello(); // static 을 사용하면 변수를 따로 선언 하지 않아도 클래스 명.함수명() 매서드 사용
10.singletons
- static 을 사용해서 data 를 공유하고, 사용되는 예시로 아래와 같이 singgleton pattern 이 있습니다.
class ClassName {
private static instance: ClassName | null = null;
public static getInstance(): ClassName {
// ClassName 으로 부터 만든 object 가 있으면 그걸 return
// ClassName 으로 부터 만든 object 가 없으면 , 만든다
if (ClassName.instance === null) {
ClassName.instance = new ClassName();
}
return ClassName.instance;
}
private constructor() {}
}
const a = ClassName.getInstance();
const b = ClassName.getInstance();
console.log(a === b);
11.상속 (inheritance)
- class 가 다른 class 를 가져다가 자신만의 기능을 추가해서 사용하는 기능 입니다.
class Parent {
constructor(protected _name: string, private _age: number) {} // protected 는 public 처럼 외부에서는 접근 할 수 없지만, 상속 관계에 있는 상태에서는 접근이 가능함
public print(): void {
console.log(`이름은 ${this._name} 이고, 나이는 ${this._age} 입니다.`);
}
protected printName(): void {
console.log(this._name);
}
}
const p = new Parent("Jacob", 80);
// p._name // name 은 protected 로 외부에서 아직 사용할 수 없음 -> 상속하게 되면 사용 가능
// p._age // private 이기 때문에 외부에서 사용할 수 없음
p.print(); // 정상적으로 print() 호출됨
// 상속
class Child extends Parent {
// 기존의 parent 에 있는 값을 over write
public _name = "John";
public gender = "male";
// 만약 child 에서 부모를 받아와서 자신의 생성자를 변경 하는 방법
constructor(age: number) {
// 무조건 자식 생성자는 super 를 먼저 호출해줘야 함 (부모를 먼저 호출 한다는 개념임)
super("Jacob Jr.", age);
this.printName();
}
}
const c = new Child(3);
c._name; //기존에는 p._name 은 protected 속성 때문에 출력이 안되지만, 상속자에서 public 으로 over-wirte 했기 때문에 출력 가능
// 결론, 상속을 사용할때, protected, private 를 사용하여 부모, 자식 각자의 영역에서 서로 영향을 미치지 않도록 잘 설정해야 함
11.abstract class
-
abstract
를 통해서 완전하지 않은class
를 표현 할 수 있으며, 완전하지 않은 class 는new
를 이용해서object
를 만들어 낼 수 없습니다. -
상속 같은 기능을 통해서 완전한 class 로 만들어서 사용할 수 있습니다.
abstract class AbstractPerson {
// abstract 를 사용하여면 class 앞에 abstract 라고 써야 됨
protected _name: string = "Jacob";
abstract setName(name: string): void;
}
// new AbstractPerson() // 기능이 완전하지 않다는것을 나타내는 abstract 를 사용했기 때문에 new 를 사용 할 수없음
class Person extends AbstractPerson {
setName(name: string): void {
// class 를 사용하기 위해서는 부모인 abstract 를 완전한 형태로 만들어 줘야 함
this._name = name;
}
}
const p = new Person();
p.setName();
🔶 🔷 📌 🔑
Reference
-
TypeScript Deep Dive - https://basarat.gitbook.io/typescript/project/compilation-context
-
TypeScript - https://www.typescriptlang.org/
-
HEROPY Tech - https://heropy.blog/2020/01/27/typescript/
Leave a comment