๐ Classes
๐ Classes
Classes๋ object(๊ฐ์ฒด)๋ฅผ ๋ง๋๋ blueprint (์ฒญ์ฌ์ง, ์ค๊ณ๋)๋ผ๊ณ ํ ์ ์๋ค.
ํด๋์ค ์ด์ ์ object๋ฅผ ๋ง๋๋ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ์ function์ด๋ค.
JavaScript์๋ class๋ es6 ๋ถํฐ ์ฌ์ฉ ๊ฐ๋ฅํ์ง๋ง ์ ๊ทผ์ ์ด์ ๊ฐ์ ๋ช๊ฐ์ง ๊ธฐ๋ฅ์ด ๋ถ์กฑํ๋ค.
typescript์์ OOP์ ์ํ ์ด์์ผ๋ก class์ ์ฌ๋ฌ๊ฐ์ง ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ณ ์๋ค.
๋ํ TypeScript ์์๋ ํด๋์ค๋ ์ฌ์ฉ์๊ฐ ๋ง๋๋ ํ์
์ค์ ํ๋๋ผ๊ณ ํ ์ ์๋ค.
class Person {}
const p1 = new Person();
console.log(p1);
class Person {
name;
constructor(name: string) {
this.name = name;
}
}
const p1 = new Person('Mark');
console.log(p1);
- class ํค์๋๋ฅผ ์ด์ฉํ์ฌ ํด๋์ค๋ฅผ ๋ง๋ค๊ณ class ์ด๋ฆ์ ๋ณดํต ๋๋ฌธ์๋ฅผ ์ด์ฉํ๋ค.
- ๋ํ new ๋ฅผ ์ด์ฉํ์ฌ class ๋ฅผ ํตํด object ๋ฅผ ๋ง๋ค ์ ์๊ณ constructor ๋ฅผ ์ด์ฉํ์ฌ object ๋ฅผ ์์ฑํ๋ฉด์ ๊ฐ์ ์ ๋ฌํ ์ ์๋ค.
- this ๋ฅผ ์ด์ฉํด์ ๋ง๋ค์ด์ง object ๋ฅผ ๊ฐ๋ฆฌํฌ ์ ์๊ณ JS ๋ก ์ปดํ์ผ๋๋ฉด es5 ์ ๊ฒฝ์ฐ function ์ผ๋ก ๋ณ๊ฒฝ๋๋ค.
๐ constructor & initialize
// strict : true
class Person {
name: string = "Mark"; //์ด๊ธฐ๊ฐ ์ค์ ๋ฐฉ๋ฒ1
age: number;
constructor(age: number) { //์ด๊ธฐ๊ฐ ์ค์ ๋ฐฉ๋ฒ2
this.age = age;
}
}
const p1: Person = new Person(20);
console.log(p1); // Person1 {}
console.log(person.age); // 20
- ์์ฑ์ ํจ์๊ฐ ์์ผ๋ฉด, ๋ํดํธ ์์ฑ์๊ฐ ๋ถ๋ฆฌ๊ณ ํ๋ก๊ทธ๋๋จธ๊ฐ ๋ง๋ ์์ฑ์๊ฐ ํ๋๋ผ๋ ์์ผ๋ฉด, ๋ํดํธ ์์ฑ์๋ ์ฌ๋ผ์ง๋ค.
- strict ๋ชจ๋์์๋ ํ๋กํผํฐ๋ฅผ ์ ์ธํ๋ ๊ณณ ๋๋ ์์ฑ์์์ ๊ฐ์ ํ ๋นํด์ผ ํ๋ค.
- ํ๋กํผํฐ๋ฅผ ์ ์ธํ๋ ๊ณณ ๋๋ ์์ฑ์์์ ๊ฐ์ ํ ๋นํ์ง ์๋ ๊ฒฝ์ฐ์๋ ! ๋ฅผ ๋ถ์ฌ์ ์ํ์ ํํํ๋ค.
- ํด๋์ค์ ํ๋กํผํฐ๊ฐ ์ ์๋์ด ์์ง๋ง, ๊ฐ์ ๋์ ํ์ง ์์ผ๋ฉด undefined ์ด๋ค.
- ์์ฑ์์๋ async ๋ฅผ ์ค์ ํ ์ ์๋ค.
โ ์ ๊ทผ ์ ์ด์ (Access Modifiers)
class Person {
public name: string = "Mark";
private _age: number;
public constructor(age: number) {
this.age = age;
}
}
const p1: Person = new Person(20);
console.log(p1); // p1.age ์ ๊ทผ ๋ถ๊ฐ
- ์ ๊ทผ ์ ์ด์์๋ public, private, protected ๊ฐ ์๊ณ ์ค์ ํ์ง ์์ผ๋ฉด public ์ด๋ค.
- ํด๋์ค ๋ด๋ถ์ ๋ชจ๋ ๊ณณ์ (์์ฑ์, ํ๋กํผํฐ, ๋ฉ์๋) ์ค์ ๊ฐ๋ฅํ๋ค.
- private ์ผ๋ก ์ค์ ํ๋ฉด ํด๋์ค ์ธ๋ถ์์ ์ ๊ทผํ ์ ์๋ค.
- protected๋ ์ธ๋ถ์์๋ ์ ๊ทผ์ด ๋ถ๊ฐํ์ง๋ง ์์๊ด๊ณ์์๋ ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค.
- ์๋ฐ์คํฌ๋ฆฝํธ์์ private ์ง์ํ์ง ์์ ์ค๋ซ๋์ ํ๋กํผํฐ๋ ๋ฉ์๋ ์ด๋ฆ ์์ _ ๋ฅผ ๋ถ์ฌ์ ํํํ๋ค.
๐จ initialization in constructor parameters
์์ฑ์์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ์์ ๋ฐ๋ก ํด๋์ค์ ํ๋กํผํฐ๋ก ์ด๊ธฐํํ๋ ๋ฐฉ๋ฒ์ผ๋ก ์์ฃผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ค.
class Person {
public constructor(public name: string, private age: number) {}
}
const p1: Person = new Person({"Mark", 20);
console.log(p1); // p1.age ์ ๊ทผ ๋ถ๊ฐ
๐ Getters & Setters
๊ฐ์ ๋ฐ์์ค๋ ๊ฒ์ get, ๊ฐ์ ์๋ก ์ค์ ํ๋ ๊ฒ์ set์ด๋ผ๊ณ ํ๋ค.
class Person {
public constructor(public name: string, private age: number) {}
}
const p1: Person = new Person({"Mark", 20);
console.log(p1); // get
p1.name = "yuni" //set
๊ฐ์ ๋ฐ์์ค๋ get์ ํ๋ ํจ์๋ฅผ getter, ๊ฐ์ ์๋ก ์ค์ ํ๋ set์ ํ๋ ํจ์๋ฅผ setter ๋ผ๊ณ ํ๋ค.
get๊ณผ set์ ๊ฐ์ด ์ค์ ๋์ด์ผ ํ๋ค.
class Person {
public constructor(public _name: string, private age: number) {}
get name() {
return this._name + "kim";
}
set name(n: string) {
this._name = n;
}
}
const p1: Person = new Person({"Mark", 20);
console.log(p1.name); // Mark kim
p1.name = "yuni" //
console.log(p1.name) // yuni kim
๐ readonly properties
readonly๊ฐ ์๋ ๊ฒฝ์ฐ ์ด๊ธฐํ๋๋ ์์ญ์์๋ง ๊ฐ์ ์ธํ
ํ ์ ์๊ณ ๋ค๋ฅธ ๊ณณ์์ ๋ฐ๊ฟ ์ ์๋ค.
๋ฐ๋ผ์ ์ด๊ธฐ๊ฐ์ ๋ณ๊ฒฝํ๊ณ ์ถ์ง ์์ ๋ readonly๋ฅผ ๋ถ์ด๋ฉด ๋๋ค.
class Person {
public readonly name: string = "Mark";
private readonly country: string;
public constructor(public _name: string, private age: number) {
this.county = "Korea";
}
hello() {
this.country = "China"; //readonly๊ฐ ์์ด์ ๋ณ๊ฒฝ ๋ถ๊ฐ
}
}
const p1: Person = new Person({"Mark", 20);
p1.name = "yuni" //readonly๊ฐ ์์ด์ ๋ณ๊ฒฝ ๋ถ๊ฐ
โฐ Index Signatures in class
์๋ ํด๋์ค ์์์ ํ๋กํผํฐ๋ฅผ ์ ์ธํ๋ฉด ํญ์ ์ด๊ธฐํ๋ฅผ ํด์คฌ์ด์ผ ํ๋๋ฐ Index Signatures๋ ํ๋กํผํฐ๊ฐ ์์ ์๋ ์์ ์๋ ์๋ ๋์ ์ธ ๊ฒฝ์ฐ์ ์ ์ฉํ๊ฒ ์ธ ์ ์๋ค.
class Student {
[index: string]: "male" | "female";
}
const a = new Students();
a.mark = "male";
a.jade = "male";
const b = new Students();
b.chloe = "female";
b.alex = "male";
console.log(a); //Students { mark: 'male', jade: 'male'}
console.log(b); //Students { chloe: 'female', alex: 'male', anna: 'female'}
โญ Static Properties & Methods
๊ณตํต์ ์ผ๋ก ์ฌ์ฉํ๊ณ ์ถ์ ํ๋กํผํฐ๊ฐ ์๋ค๋ฉด ์์ static์ ๋ถ์ด๋ฉด ๋๋ค.
class Person {
public hello() {
console.log('์๋
');
}
}
const p1 = new Person();
p1.hello();
//static์ ๋ถ์ด๋ฉด
class Person {
public static hello() {
console.log('์๋
');
}
}
const p1 = new Person();
p1.hello(); //์๋ฌ
Person.hello();
static์ด ๋ถ์ ํจ์๋ ํจ์๋ก ์๊ฐํ์ง ์์ผ๋ฏ๋ก p1.hello()๋ก๋ ์ ๊ทผ ๋ถ๊ฐํ๋ค.
class Person {
private static CITY = "Seoul";
public hello() {
console.log('์๋
', Person.CITY);
}
public change() {
person.CITY = "LA";
}
}
const p1 = new Person();
p1.hello(); //์๋
Seoul
const p2 = new Person();
p2.hello(); //์๋
Seoul
p1.change();
p2.hello(); //์๋
LA
1๏ธโฃ Singletons
Singletons pattern์ด๋ ์ดํ์ด ์คํ๋๋ ์ค๊ฐ์ ํด๋์ค๋ก๋ถํฐ ๋จ ํ๋์ ๊ฐ์ฒด๋ง ์์ฑํด์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
class ClassName {
const a = new ClassName();
const b = new ClassName();
๋จผ์ new๋ก ํด๋์ค ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ ๊ฒ์ ๋ง์๋ณด์.
class ClassName {
private constructor(){}
}
const a = new ClassName();
const b = new ClassName();
์ด๋ฒ์๋ ๋ค๋ฅธ ๋งค๊ฐ์ฒด๋ฅผ ์ด์ฉํด ์์ฑ๋ ๊ฐ์ฒด๋ฅผ ๋ฌ๋ผ๊ณ ํ์ฌ ์ฑ๊ธํค ํจํด์ ๋ง๋ค ์ ์๋ค.
class ClassName {
private static instance = ClassName | null = null;
public static getInstance(): ClassName {
//ClassName์ผ๋ก ๋ถํฐ ๋ง๋ ๊ฐ์ฒด๊ฐ ์์ผ๋ฉด ๋ฆฌํด, ์์ผ๋ฉด ๋ง๋ค์ด์ ๋ฆฌํด
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); //true
๐ช ์์ (Inheritance)
ํด๋์ค๊ฐ ๋ค๋ฅธ ํด๋์ค๋ฅผ ๊ฐ์ ธ๋ค๊ฐ ์์ ๋ง์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ ๊ฒ์ด ์์์ด๋ค.
๋ถ๋ชจ ํด๋์ค์ธ Parent๋ฅผ ์์๋ฐ์ ์์ ํด๋์ค Child๋ ์์ฑ์๋ฅผ ๊ทธ๋๋ก ๋ฐ์์ค๊ฒ ๋๋ค.
//๋ถ๋ชจ ํด๋์ค
class Parent {
constructor(protected _name: string, private _age: number) {}
public print(): void {
console.log(`์ด๋ฆ์ ${this._name}์ด๊ณ ๋์ด๋ ${this._age}์
๋๋ค`);
}
}
const p = new Parent("yuni", 27);
p.print();//์ด๋ฆ์ yuni์ด๊ณ ๋์ด๋ 27์
๋๋ค
๋ถ๋ชจ ํด๋์ค์์ ์ ์๋ ๊ฒ์ ์์ ํด๋์ค์์ ์ฌ์ ์ ํ๋ ๊ฒ์ด ์ค๋ฒ๋ผ์ด๋ฉ์ด๋ค.
//์์
class Child extends Parent {
//์ค๋ฒ๋ผ์ด๋ฉ
// public _name = "mark";
//์๋ก ์ถ๊ฐ
public gender = 'male';
//์ค๋ฒ๋ผ์ด๋ฉ
constructor(age: number) {
//super๋ก ๋ถ๋ชจ ์์ฑ์ ํธ์ถ
super('mark',age);
}
}
const c = new Child(2);
c.print();//์ด๋ฆ์ mark์ด๊ณ ๋์ด๋ 2์
๋๋ค
๋ถ๋ชจ ํด๋์ค์ ์๋ ํจ์๋ฅผ ๊ฐ์ ธ์ค๋ ค๋ฉด super๊ฐ ๋จผ์ ์ค๊ณ ๊ทธ ๋ค์์ this.ํจ์๊ฐ ์์ผ ํจ์ ์ฃผ์ํ์.
class Parent {
constructor(protected _name: string, private _age: number) {}
public print(): void {
console.log(`์ด๋ฆ์ ${this._name}์ด๊ณ ๋์ด๋ ${this._age}์
๋๋ค`);
}
protected printName(): void {
console.log(this._name); //mark
}
}
//์์
class Child extends Parent {
//์ค๋ฒ๋ผ์ด๋ฉ
constructor(age: number) {
super('mark',age);
this.printName();
}
}
const c = new Child(2);
c.print(); //์ด๋ฆ์ mark์ด๊ณ ๋์ด๋ 2์
๋๋ค
โ Abstract Classes
Abstract๋ฅผ ์ฌ์ฉํ๋ฉด ์์ ํ์ง ์์ ํด๋์ค๋ฅผ ํํํ ์ ์๋ค.
ํด๋์ค ์ด๋ฆ ๋งจ ์์ abstract๋ฅผ ๋ถ์ด๋ฉด ๊ทธ ํด๋์ค ์์ ์๋ ๊ธฐ๋ฅ์ด ์์ ํ์ง ์์๋ ๋๋ฉฐ ๊ทธ ๊ธฐ๋ฅ ์์๋ abstract๋ฅผ ๋ถ์ฌ์ฃผ๋ฉด ๋๋ค.
abstract class AbstractPerson {
protected _name: string = 'yuni';
abstract setName(name: string): void;
}
new AbstractPerson(); //abstract๋ผ์ ๋ถ๊ฐ
abstract ํด๋์ค๋ ๊ธฐ๋ฅ์ด ์์ ํ์ง ์๊ธฐ ๋๋ฌธ์ new๋ฅผ ํ ์ ์๋ค.
์์์ ํตํด ์ค๋ฒ๋ผ์ด๋ฉ์ผ๋ก abstractํด๋์ค๋ฅผ ์์ ํ๊ฒ ๋ง๋ ํ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
abstract class AbstractPerson {
protected _name: string = 'yuni';
abstract setName(name: string): void;
}
new AbstractPerson(); //abstract๋ผ์ ๋ถ๊ฐ
//์์
class Person extends AbstractPerson {
setName(name: string): void {
this._name = name;
}
}
const p = new Person();
p.setName();