Skip to content

Latest commit

Β 

History

History
516 lines (388 loc) Β· 21.7 KB

classes.md

File metadata and controls

516 lines (388 loc) Β· 21.7 KB

μ†Œκ°œ (Introduction)

κΈ°μ‘΄Β JavaScriptλŠ”Β μž¬μ‚¬μš©ν• Β μˆ˜Β μžˆλŠ”Β μ»΄ν¬λ„ŒνŠΈλ₯ΌΒ λ§Œλ“€κΈ°Β μœ„ν•΄Β ν•¨μˆ˜μ™€Β ν”„λ‘œν† νƒ€μž…-κΈ°λ°˜Β μƒμ†μ„Β μ‚¬μš©ν–ˆμ§€λ§Œ, 객체 지ν–₯Β μ ‘κ·ΌΒ λ°©μ‹μ—Β μ΅μˆ™ν•œΒ ν”„λ‘œκ·Έλž˜λ¨Έμ˜Β μž…μž₯μ—μ„œλŠ”Β ν΄λž˜μŠ€κ°€ ν•¨μˆ˜λ₯Ό 상속받고 이런 ν΄λž˜μŠ€μ—μ„œΒ κ°μ²΄κ°€Β λ§Œλ“€μ–΄μ§€λŠ” 것에 λ‹€μ†ŒΒ μ–΄μƒ‰ν•¨μ„Β λŠλ‚„Β μˆ˜Β μžˆμŠ΅λ‹ˆλ‹€. ECMAScriptΒ 6λ‘œλ„Β μ•Œλ €μ§„Β ECMAScriptΒ 2015λ₯ΌΒ μ‹œμž‘μœΌλ‘œ JavaScriptΒ ν”„λ‘œκ·Έλž˜λ¨Έλ“€μ€Β μ΄λŸ°Β κ°μ²΄-지ν–₯적 클래슀-κΈ°λ°˜μ˜Β μ ‘κ·ΌΒ λ°©μ‹μ„Β μ‚¬μš©ν•΄μ„œΒ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„Β λ§Œλ“€Β μˆ˜Β μžˆμŠ΅λ‹ˆλ‹€. TypeScriptμ—μ„œλŠ”Β λ‹€μŒΒ λ²„μ „μ˜Β JavaScriptλ₯ΌΒ κΈ°λ‹€λ¦΄Β ν•„μš”Β μ—†μ΄Β κ°œλ°œμžλ“€μ΄Β μ΄λŸ¬ν•œΒ κΈ°λ²•λ“€μ„Β μ‚¬μš©ν•  수 있게 ν•΄μ£Όλ©°, 기쑴의JavaScriptλ‘œΒ μ»΄νŒŒμΌν•˜μ—¬Β μ£Όμš”Β λΈŒλΌμš°μ €μ™€Β ν”Œλž«νΌμ—μ„œΒ λ™μž‘ν•˜κ²ŒΒ ν•©λ‹ˆλ‹€.

클래슀 (Classes)

κ°„λ‹¨ν•œ 클래슀-기반 예제λ₯Ό μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€:

class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}

let greeter = new Greeter("world");

C# μ΄λ‚˜ Javaλ₯Ό μ‚¬μš©ν•΄λ΄€λ‹€λ©΄, μ΅μˆ™ν•œ ꡬ문일 κ²ƒμž…λ‹ˆλ‹€. μƒˆλ‘œμš΄ 클래슀 Greeterλ₯Ό μ„ μ–Έν–ˆμŠ΅λ‹ˆλ‹€. 이 ν΄λž˜μŠ€λŠ” 3개의 멀버λ₯Ό 가지고 μžˆμŠ΅λ‹ˆλ‹€: greeting ν”„λ‘œνΌν‹°, μƒμ„±μž 그리고 greet λ©”μ„œλ“œ μž…λ‹ˆλ‹€.

클래슀 μ•ˆμ—μ„œ 클래슀의 멀버λ₯Ό μ°Έμ‘°ν•  λ•Œ this.λ₯Ό μ•žμ— λ§λΆ™μ΄λŠ” 것을 μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€. 이것은 멀버에 μ ‘κ·Όν•˜λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.

λ§ˆμ§€λ§‰ μ€„μ—μ„œ, newλ₯Ό μ‚¬μš©ν•˜μ—¬ Greeter클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. 이 μ½”λ“œλŠ” 이전에 μ •μ˜ν•œ μƒμ„±μžλ₯Ό ν˜ΈμΆœν•˜μ—¬ Greeter ν˜•νƒœμ˜ μƒˆλ‘œμš΄ 객체λ₯Ό λ§Œλ“€κ³ , μƒμ„±μžλ₯Ό μ‹€ν–‰ν•΄ μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.

상속 (Inheritance)

TypeScriptμ—μ„œλŠ”, 일반적인 객체-지ν–₯ νŒ¨ν„΄μ„ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 클래슀-기반 ν”„λ‘œκ·Έλž˜λ°μ˜ κ°€μž₯ 기본적인 νŒ¨ν„΄ 쀑 ν•˜λ‚˜λŠ” 상속을 μ΄μš©ν•˜μ—¬ 이미 μ‘΄μž¬ν•˜λŠ” 클래슀λ₯Ό ν™•μž₯ν•΄ μƒˆλ‘œμš΄ 클래슀λ₯Ό λ§Œλ“€ 수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

예제λ₯Ό μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€:

class Animal {
    move(distanceInMeters: number = 0) {
        console.log(`Animal moved ${distanceInMeters}m.`);
    }
}

class Dog extends Animal {
    bark() {
        console.log('Woof! Woof!');
    }
}

const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();

상속 κΈ°λŠ₯을 λ³΄μ—¬μ£ΌλŠ” κ°€μž₯ 기본적인 μ˜ˆμ œμž…λ‹ˆλ‹€: ν΄λž˜μŠ€λŠ” 기초 ν΄λž˜μŠ€λ‘œλΆ€ν„° ν”„λ‘œνΌν‹°μ™€ λ©”μ„œλ“œλ₯Ό μƒμ†λ°›μŠ΅λ‹ˆλ‹€. μ—¬κΈ°μ„œ, Dog은 extends ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ Animalμ΄λΌλŠ” 기초 ν΄λž˜μŠ€λ‘œλΆ€ν„° νŒŒμƒλœ νŒŒμƒ ν΄λž˜μŠ€μž…λ‹ˆλ‹€. νŒŒμƒλœ ν΄λž˜μŠ€λŠ” ν•˜μœ„ν΄λž˜μŠ€(subclasses), 기초 ν΄λž˜μŠ€λŠ” μƒμœ„ν΄λž˜μŠ€(superclasses) 라고 λΆˆλ¦¬κΈ°λ„ ν•©λ‹ˆλ‹€.

DogλŠ” Animal의 κΈ°λŠ₯을 ν™•μž₯ν•˜κΈ° λ•Œλ¬Έμ—, bark()와 move()λ₯Ό λͺ¨λ‘ 가진 Dog μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 수 μžˆμŠ΅λ‹ˆλ‹€.

쑰금 더 λ³΅μž‘ν•œ 예제λ₯Ό μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

class Animal {
    name: string;
    constructor(theName: string) { this.name = theName; }
    move(distanceInMeters: number = 0) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}

class Snake extends Animal {
    constructor(name: string) { super(name); }
    move(distanceInMeters = 5) {
        console.log("Slithering...");
        super.move(distanceInMeters);
    }
}

class Horse extends Animal {
    constructor(name: string) { super(name); }
    move(distanceInMeters = 45) {
        console.log("Galloping...");
        super.move(distanceInMeters);
    }
}

let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");

sam.move();
tom.move(34);

이 μ˜ˆμ œλŠ” μ•žμ—μ„œ μ–ΈκΈ‰ν•˜μ§€ μ•Šμ€ λͺ‡ 가지 κΈ°λŠ₯을 λ‹€λ£Ήλ‹ˆλ‹€. μ΄λ²ˆμ—λ„ extends ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ Animal의 ν•˜μœ„ν΄λž˜μŠ€λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€: Horse와 Snake.

이전 μ˜ˆμ œμ™€ ν•œ 가지 λ‹€λ₯Έ 뢀뢄은 νŒŒμƒλœ 클래슀의 μƒμ„±μž ν•¨μˆ˜λŠ” 기초 클래슀의 μƒμ„±μžλ₯Ό μ‹€ν–‰ν•  super()λ₯Ό ν˜ΈμΆœν•΄μ•Ό ν•œλ‹€λŠ” μ μž…λ‹ˆλ‹€. λ”μš±μ΄ μƒμ„±μž λ‚΄μ—μ„œ this에 μžˆλŠ” ν”„λ‘œνΌν‹°μ— μ ‘κ·Όν•˜κΈ° 전에 super()λ₯Ό λ¨Όμ € ν˜ΈμΆœν•΄μ•Ό ν•©λ‹ˆλ‹€. 이 뢀뢄은 TypeScriptμ—μ„œ μ€‘μš”ν•œ κ·œμΉ™μž…λ‹ˆλ‹€.

λ˜ν•œ 이 μ˜ˆμ œλŠ” 기초 클래슀의 λ©”μ„œλ“œλ₯Ό ν•˜μœ„ν΄λž˜μŠ€μ— νŠΉν™”λœ λ©”μ„œλ“œλ‘œ μ˜€λ²„λΌμ΄λ“œν•˜λŠ” 방법을 λ³΄μ—¬μ€λ‹ˆλ‹€. μ—¬κΈ°μ„œ Snake와 HorseλŠ” Animal의 moveλ₯Ό μ˜€λ²„λΌμ΄λ“œν•΄μ„œ 각각 클래슀의 νŠΉμ„±μ— 맞게 κΈ°λŠ₯을 가진 moveλ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. tom은 Animal둜 μ„ μ–Έλ˜μ—ˆμ§€λ§Œ Horse의 값을 κ°€μ§€λ―€λ‘œ tom.move(34)λŠ” Horse의 μ˜€λ²„λΌμ΄λ”© λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€.

Slithering...
Sammy the Python moved 5m.
Galloping...
Tommy the Palomino moved 34m.

Public, private 그리고 protected μ§€μ •μž (Public, private, and protected modifiers)

기본적으둜 곡개 (Public by default)

우리 μ˜ˆμ œμ—μ„œλŠ”, ν”„λ‘œκ·Έλž¨ λ‚΄μ—μ„œ μ„ μ–Έλœ 멀버듀에 자유둭게 μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ‹€λ₯Έ μ–Έμ–΄μ˜ ν΄λž˜μŠ€κ°€ μ΅μˆ™ν•˜λ‹€λ©΄, μœ„ μ˜ˆμ œμ—μ„œ public을 μ‚¬μš©ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€λŠ” 점을 μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, C#μ—μ„œλŠ” λ…ΈμΆœ μ‹œν‚¬ 각 멀버에 public을 λΆ™μ—¬μ•Ό ν•©λ‹ˆλ‹€. TypeScriptμ—μ„œλŠ” 기본적으둜 각 λ©€λ²„λŠ” publicμž…λ‹ˆλ‹€.

λͺ…μ‹œμ μœΌλ‘œ 멀버λ₯Ό public으둜 ν‘œμ‹œν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. 이전 μ„Ήμ…˜μ˜ Animal 클래슀λ₯Ό λ‹€μŒκ³Ό 같은 λ°©μ‹μœΌλ‘œ μž‘μ„±ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

class Animal {
    public name: string;
    public constructor(theName: string) { this.name = theName; }
    public move(distanceInMeters: number) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}

ECMAScript λΉ„κ³΅κ°œ ν•„λ“œ (ECMAScript Private Fields)

TypeScript 3.8μ—μ„œ, TypeScriptλŠ” λΉ„κ³΅κ°œ ν•„λ“œλ₯Ό μœ„ν•œ JavaScript의 μƒˆλ‘œμš΄ 문법을 μ§€μ›ν•©λ‹ˆλ‹€:

class Animal {
    #name: string;
    constructor(theName: string) { this.#name = theName; }
}

new Animal("Cat").#name; // ν”„λ‘œνΌν‹° '#name'은 λΉ„κ³΅κ°œ μ‹λ³„μžμ΄κΈ° λ•Œλ¬Έμ— 'Animal' 클래슀 외뢀에선 μ ‘κ·Όν•  수 μ—†μŠ΅λ‹ˆλ‹€.

이 문법은 JavaScript λŸ°νƒ€μž„μ— λ‚΄μž₯λ˜μ–΄ 있으며, 각각의 λΉ„κ³΅κ°œ ν•„λ“œμ˜ 격리λ₯Ό 더 잘 보μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€. ν˜„μž¬ TypeScript 3.8 릴리즈 λ…ΈνŠΈμ— λΉ„κ³΅κ°œ ν•„λ“œμ— λŒ€ν•΄ μžμ„Ένžˆ λ‚˜μ™€μžˆμŠ΅λ‹ˆλ‹€.

TypeScript의 private μ΄ν•΄ν•˜κΈ° (Understanding TypeScript’s private)

TypeScriptμ—λŠ” 멀버λ₯Ό ν¬ν•¨ν•˜λŠ” 클래슀 μ™ΈλΆ€μ—μ„œ 이 멀버에 μ ‘κ·Όν•˜μ§€ λͺ»ν•˜λ„둝 멀버λ₯Ό private으둜 ν‘œμ‹œν•˜λŠ” 방법이 μžˆμŠ΅λ‹ˆλ‹€. 예:

class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

new Animal("Cat").name; // 였λ₯˜: 'name'은 λΉ„κ³΅κ°œλ‘œ μ„ μ–Έλ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€;

TypeScriptλŠ” ꡬ쑰적인 νƒ€μž… μ‹œμŠ€ν…œμž…λ‹ˆλ‹€. λ‘κ°œμ˜ λ‹€λ₯Έ νƒ€μž…μ„ 비ꡐ할 λ•Œ μ–΄λ””μ„œ μ™”λŠ”μ§€ 상관없이 λͺ¨λ“  λ©€λ²„μ˜ νƒ€μž…μ΄ ν˜Έν™˜ λœλ‹€λ©΄, κ·Έ νƒ€μž…λ“€ μžμ²΄κ°€ ν˜Έν™˜ κ°€λŠ₯ν•˜λ‹€κ³  λ§ν•©λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ private 및 protected 멀버가 μžˆλŠ” νƒ€μž…λ“€μ„ 비ꡐ할 λ•ŒλŠ” νƒ€μž…μ„ λ‹€λ₯΄κ²Œ μ²˜λ¦¬ν•©λ‹ˆλ‹€. ν˜Έν™˜λœλ‹€κ³  νŒλ‹¨λ˜λŠ” 두 개의 νƒ€μž… 쀑 ν•œ μͺ½μ—μ„œ private 멀버λ₯Ό 가지고 μžˆλ‹€λ©΄, λ‹€λ₯Έ ν•œ μͺ½λ„ 무쑰건 λ™μΌν•œ 선언에 private 멀버λ₯Ό 가지고 μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€. 이것은 protected 멀버에도 μ μš©λ©λ‹ˆλ‹€.

μ‹€μ œλ‘œ μ–΄λ–»κ²Œ μž‘λ™ν•˜λŠ”μ§€ μ•Œμ•„λ³΄κΈ° μœ„ν•΄ λ‹€μŒ 예제λ₯Ό μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€:

class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

class Rhino extends Animal {
    constructor() { super("Rhino"); }
}

class Employee {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

let animal = new Animal("Goat");
let rhino = new Rhino();
let employee = new Employee("Bob");

animal = rhino;
animal = employee; // 였λ₯˜: 'Animal'κ³Ό 'Employee'은 ν˜Έν™˜λ  수 μ—†μŒ.

이 μ˜ˆμ œμ—μ„œλŠ” Animalκ³Ό Animal의 ν•˜μœ„ν΄λž˜μŠ€μΈ Rhinoκ°€ μžˆμŠ΅λ‹ˆλ‹€. Animalκ³Ό ν˜•νƒœκ°€ κ°™μ•„λ³΄μ΄λŠ” EmployeeλΌλŠ” μƒˆλ‘œμš΄ ν΄λž˜μŠ€λ„ μžˆμŠ΅λ‹ˆλ‹€. 이 ν΄λž˜μŠ€λ“€μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜μ—¬ ν• λ‹Ήν•˜κ³  μ–΄λ–»κ²Œ μž‘λ™ν•˜λŠ”μ§€ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€. Animalκ³Ό RhinoλŠ” Animal의 private name:stringμ΄λΌλŠ” λ™μΌν•œ μ„ μ–ΈμœΌλ‘œλΆ€ν„° private 뢀뢄을 κ³΅μœ ν•˜κΈ° λ•Œλ¬Έμ— ν˜Έν™˜μ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€. ν•˜μ§€λ§Œ Employee κ²½μš°λŠ” 그렇지 μ•ŠμŠ΅λ‹ˆλ‹€. Employeeλ₯Ό Animal에 ν• λ‹Ήν•  λ•Œ, νƒ€μž…μ΄ ν˜Έν™˜λ˜μ§€ μ•Šλ‹€λŠ” 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€. EmployeeλŠ” nameμ΄λΌλŠ” private 멀버λ₯Ό 가지고 μžˆμ§€λ§Œ, Animalμ—μ„œ μ„ μ–Έν•œ 것이 μ•„λ‹ˆκΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

protected μ΄ν•΄ν•˜κΈ° (Understanding protected)

protected μ§€μ •μžλ„ protected둜 μ„ μ–Έλœ 멀버λ₯Ό νŒŒμƒλœ 클래슀 λ‚΄μ—μ„œ μ ‘κ·Όν•  수 μžˆλ‹€λŠ” 점만 μ œμ™Έν•˜λ©΄ privateμ§€μ •μžμ™€ 맀우 μœ μ‚¬ν•˜κ²Œ λ™μž‘ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€λ©΄,

class Person {
    protected name: string;
    constructor(name: string) { this.name = name; }
}

class Employee extends Person {
    private department: string;

    constructor(name: string, department: string) {
        super(name);
        this.department = department;
    }

    public getElevatorPitch() {
        return `Hello, my name is ${this.name} and I work in ${this.department}.`;
    }
}

let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
console.log(howard.name); // 였λ₯˜

Person μ™ΈλΆ€μ—μ„œ name을 μ‚¬μš©ν•  수 μ—†μ§€λ§Œ, EmployeeλŠ” Personμ—μ„œ νŒŒμƒλ˜μ—ˆκΈ° λ•Œλ¬Έμ— Employee의 μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œ λ‚΄μ—μ„œλŠ” μ—¬μ „νžˆ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μƒμ„±μž λ˜ν•œ protected둜 ν‘œμ‹œλ  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” 클래슀λ₯Ό ν¬ν•¨ν•˜λŠ” 클래슀 μ™ΈλΆ€μ—μ„œ μΈμŠ€ν„΄μŠ€ν™” ν•  수 μ—†μ§€λ§Œ ν™•μž₯ ν•  수 μžˆμŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€. 예λ₯Ό λ“€λ©΄,

class Person {
    protected name: string;
    protected constructor(theName: string) { this.name = theName; }
}

// EmployeeλŠ” Person을 ν™•μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
class Employee extends Person {
    private department: string;

    constructor(name: string, department: string) {
        super(name);
        this.department = department;
    }

    public getElevatorPitch() {
        return `Hello, my name is ${this.name} and I work in ${this.department}.`;
    }
}

let howard = new Employee("Howard", "Sales");
let john = new Person("John"); // 였λ₯˜: 'Person'의 μƒμ„±μžλŠ” protected μž…λ‹ˆλ‹€.

μ½κΈ°μ „μš© μ§€μ •μž (Readonly modifier)

readonlyν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ ν”„λ‘œνΌν‹°λ₯Ό μ½κΈ°μ „μš©μœΌλ‘œ λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€. μ½κΈ°μ „μš© ν”„λ‘œνΌν‹°λ“€μ€ μ„ μ–Έ λ˜λŠ” μƒμ„±μžμ—μ„œ μ΄ˆκΈ°ν™”ν•΄μ•Ό ν•©λ‹ˆλ‹€.

class Octopus {
    readonly name: string;
    readonly numberOfLegs: number = 8;
    constructor (theName: string) {
        this.name = theName;
    }
}
let dad = new Octopus("Man with the 8 strong legs");
dad.name = "Man with the 3-piece suit"; // 였λ₯˜! name은 μ½κΈ°μ „μš© μž…λ‹ˆλ‹€.

λ§€κ°œλ³€μˆ˜ ν”„λ‘œνΌν‹° (Parameter properties)

λ§ˆμ§€λ§‰ 예제의 Octopus 클래슀 λ‚΄μ—μ„œ nameμ΄λΌλŠ” μ½κΈ°μ „μš© 멀버와 theNameμ΄λΌλŠ” μƒμ„±μž λ§€κ°œλ³€μˆ˜λ₯Ό μ„ μ–Έν–ˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” Octopus의 μƒμ„±μžκ°€ μˆ˜ν–‰λœ 후에 theName의 값에 μ ‘κ·Όν•˜κΈ° μœ„ν•΄μ„œ ν•„μš”ν•©λ‹ˆλ‹€. λ§€κ°œλ³€μˆ˜ ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•˜λ©΄ ν•œ κ³³μ—μ„œ 멀버λ₯Ό λ§Œλ“€κ³  μ΄ˆκΈ°ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ‹€μŒμ€ λ§€κ°œλ³€μˆ˜ ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•œ 더 κ°œμ •λœ Octopusν΄λž˜μŠ€μž…λ‹ˆλ‹€.

class Octopus {
    readonly numberOfLegs: number = 8;
    constructor(readonly name: string) {
    }
}

μƒμ„±μžμ— 짧아진 readonly name: string νŒŒλΌλ―Έν„°λ₯Ό μ‚¬μš©ν•˜μ—¬ theName을 μ œκ±°ν•˜κ³  name 멀버λ₯Ό μƒμ„±ν•˜κ³  μ΄ˆκΈ°ν™”ν–ˆμŠ΅λ‹ˆλ‹€. 즉 μ„ μ–Έκ³Ό 할당을 ν•œ 곳으둜 ν†΅ν•©ν–ˆμŠ΅λ‹ˆλ‹€.

λ§€κ°œλ³€μˆ˜ ν”„λ‘œνΌν‹°λŠ” μ ‘κ·Ό μ§€μ •μžλ‚˜ readonly λ˜λŠ” λ‘˜ λͺ¨λ‘λ₯Ό μƒμ„±μž λ§€κ°œλ³€μˆ˜μ— μ ‘λ‘μ–΄λ‘œ λΆ™μ—¬ μ„ μ–Έν•©λ‹ˆλ‹€. λ§€κ°œλ³€μˆ˜ ν”„λ‘œνΌν‹°μ— private을 μ‚¬μš©ν•˜λ©΄ λΉ„κ³΅κ°œ 멀버λ₯Ό μ„ μ–Έν•˜κ³  μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€. λ§ˆμ°¬κ°€μ§€λ‘œ, public, protected, readonly도 λ™μΌν•˜κ²Œ μž‘μš©ν•©λ‹ˆλ‹€.

μ ‘κ·Όμž (Accessors)

TypeScriptλŠ” 객체의 멀버에 λŒ€ν•œ 접근을 κ°€λ‘œμ±„λŠ” λ°©μ‹μœΌλ‘œ getters/settersλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 각 객체의 멀버에 μ ‘κ·Όν•˜λŠ” 방법을 μ„Έλ°€ν•˜κ²Œ μ œμ–΄ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

κ°„λ‹¨ν•œ 클래슀λ₯Ό getκ³Ό set을 μ‚¬μš©ν•˜λ„λ‘ λ³€ν™˜ν•΄λ΄…μ‹œλ‹€. λ¨Όμ € getters와 settersκ°€ μ—†λŠ” 예제둜 μ‹œμž‘ν•©λ‹ˆλ‹€.

class Employee {
    fullName: string;
}

let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
    console.log(employee.fullName);
}

μ‚¬λžŒλ“€μ΄ μž„μ˜λ‘œ fullName을 직접 μ„€μ •ν•  수 μžˆλ„λ‘ ν—ˆμš©ν•˜λŠ” 것은 맀우 νŽΈλ¦¬ν•˜μ§€λ§Œ, μš°λ¦¬λŠ” fullName이 섀정될 λ•Œ λͺ‡ 가지 μ œμ•½ 쑰건이 μ μš©λ˜λŠ” 것을 원할 수 μžˆμŠ΅λ‹ˆλ‹€.

이 λ²„μ „μ—μ„œλŠ” λ°±μ—… λ°μ΄ν„°λ² μ΄μŠ€ ν•„λ“œμ˜ μ΅œλŒ€ 길이와 ν˜Έν™˜λ˜λŠ”μ§€ ν™•μΈν•˜κΈ° μœ„ν•΄ newName의 길이λ₯Ό ν™•μΈν•˜λŠ” setterλ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€. λ§Œμ•½ μ΅œλŒ€ 길이λ₯Ό μ΄ˆκ³Όν•œλ‹€λ©΄, ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œμ— λ¬Έμ œκ°€ μžˆλ‹€λŠ” 것을 μ•Œλ¦¬κΈ° μœ„ν•΄ 였λ₯˜λ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€.

기쑴의 κΈ°λŠ₯을 μœ μ§€ν•˜κΈ° μœ„ν•΄, fullName을 μˆ˜μ •ν•˜μ§€ μ•ŠλŠ” κ°„λ‹¨ν•œ getter도 μΆ”κ°€ν•©λ‹ˆλ‹€.

const fullNameMaxLength = 10;

class Employee {
    private _fullName: string;

    get fullName(): string {
        return this._fullName;
    }

    set fullName(newName: string) {
        if (newName && newName.length > fullNameMaxLength) {
            throw new Error("fullName has a max length of " + fullNameMaxLength);
        }

        this._fullName = newName;
    }
}

let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
    console.log(employee.fullName);
}

μ ‘κ·Όμžκ°€ κ°’μ˜ 길이λ₯Ό ν™•μΈν•˜κ³  μžˆλŠ”μ§€ κ²€μ¦ν•˜κΈ° μœ„ν•΄μ„œ, 10μžκ°€ λ„˜λŠ” 이름을 ν• λ‹Ήν•˜κ³  였λ₯˜κ°€ λ°œμƒν•¨μ„ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

μ ‘κ·Όμžμ— λŒ€ν•΄ μ£Όμ˜ν•΄μ•Ό ν•  사항:

λ¨Όμ € μ ‘κ·ΌμžλŠ” ECMAScript 5 이상을 좜λ ₯ν•˜λ„λ‘ 컴파일러λ₯Ό μ„€μ •ν•΄μ•Ό ν•©λ‹ˆλ‹€. ECMAScript 3으둜의 ν•˜ν–₯ 쑰정은 μ§€μ›λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λ‘˜μ§Έ, getκ³Ό set이 μ—†λŠ” μ ‘κ·ΌμžλŠ” μžλ™μœΌλ‘œ readonly둜 μœ μΆ”λ©λ‹ˆλ‹€. μ΄λŠ” ν”„λ‘œνΌν‹° λ‚΄μ˜ μ‚¬μš©μžλ“€μ΄ λ³€κ²½ν•  수 μ—†μŒμ„ μ•Œ 수 있기 λ•Œλ¬Έμ— μ½”λ“œ λ‚΄μ—μ„œ .d.ts νŒŒμΌμ„ 생성할 λ•Œ μœ μš©ν•©λ‹ˆλ‹€.

μ „μ—­ ν”„λ‘œνΌν‹° (Static Properties)

μ§€κΈˆκΉŒμ§€λŠ” μΈμŠ€ν„΄μŠ€ν™”λ  λ•Œ 객체에 λ³΄μ΄λŠ” μΈμŠ€ν„΄μŠ€ 멀버에 λŒ€ν•΄μ„œλ§Œ μ‚΄νŽ΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€. λ˜ν•œ μš°λ¦¬λŠ” μΈμŠ€ν„΄μŠ€κ°€ μ•„λ‹Œ 클래슀 μžμ²΄μ—μ„œ λ³΄μ΄λŠ” μ „μ—­ 멀버λ₯Ό 생성할 수 μžˆμŠ΅λ‹ˆλ‹€. 이 μ˜ˆμ œμ—μ„œλŠ” λͺ¨λ“  grid의 일반적인 값이기 λ•Œλ¬Έμ— origin에 static을 μ‚¬μš©ν•©λ‹ˆλ‹€. 각 μΈμŠ€ν„΄μŠ€λŠ” 클래슀 이름을 μ•žμ— λΆ™μ—¬ 이 값에 μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€. μΈμŠ€ν„΄μŠ€ μ ‘κ·Ό μ•žμ— this.λ₯Ό λΆ™μ΄λŠ” 것과 λΉ„μŠ·ν•˜κ²Œ μ—¬κΈ°μ„  μ „μ—­ μ ‘κ·Ό μ•žμ— Grid.λ₯Ό λΆ™μž…λ‹ˆλ‹€.

class Grid {
    static origin = {x: 0, y: 0};
    calculateDistanceFromOrigin(point: {x: number; y: number;}) {
        let xDist = (point.x - Grid.origin.x);
        let yDist = (point.y - Grid.origin.y);
        return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
    }
    constructor (public scale: number) { }
}

let grid1 = new Grid(1.0);  // 1x scale
let grid2 = new Grid(5.0);  // 5x scale

console.log(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));
console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));

좔상 클래슀 (Abstract Classes)

좔상 ν΄λž˜μŠ€λŠ” λ‹€λ₯Έ ν΄λž˜μŠ€λ“€μ΄ νŒŒμƒλ  수 μžˆλŠ” 기초 ν΄λž˜μŠ€μž…λ‹ˆλ‹€. 좔상 ν΄λž˜μŠ€λŠ” 직접 μΈμŠ€ν„΄μŠ€ν™”ν•  수 μ—†μŠ΅λ‹ˆλ‹€. 좔상 ν΄λž˜μŠ€λŠ” μΈν„°νŽ˜μ΄μŠ€μ™€ 달리 멀버에 λŒ€ν•œ κ΅¬ν˜„ μ„ΈλΆ€ 정보λ₯Ό 포함할 수 μžˆμŠ΅λ‹ˆλ‹€. abstract ν‚€μ›Œλ“œλŠ” 좔상 클래슀뿐만 μ•„λ‹ˆλΌ 좔상 클래슀 λ‚΄μ—μ„œ 좔상 λ©”μ„œλ“œλ₯Ό μ •μ˜ν•˜λŠ”λ° μ‚¬μš©λ©λ‹ˆλ‹€.

abstract class Animal {
    abstract makeSound(): void;
    move(): void {
        console.log("roaming the earth...");
    }
}

좔상 클래슀 λ‚΄μ—μ„œ μΆ”μƒμœΌλ‘œ ν‘œμ‹œλœ λ©”μ„œλ“œλŠ” κ΅¬ν˜„μ„ ν¬ν•¨ν•˜μ§€ μ•ŠμœΌλ©° λ°˜λ“œμ‹œ νŒŒμƒλœ ν΄λž˜μŠ€μ—μ„œ κ΅¬ν˜„λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€. 좔상 λ©”μ„œλ“œλŠ” μΈν„°νŽ˜μ΄μŠ€ λ©”μ„œλ“œμ™€ λΉ„μŠ·ν•œ 문법을 κ³΅μœ ν•©λ‹ˆλ‹€. λ‘˜ λ‹€ λ©”μ„œλ“œ 본문을 ν¬ν•¨ν•˜μ§€ μ•Šκ³  λ©”μ„œλ“œλ₯Ό μ •μ˜ν•©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 좔상 λ©”μ„œλ“œλŠ” λ°˜λ“œμ‹œ abstract ν‚€μ›Œλ“œλ₯Ό 포함해야 ν•˜λ©°, μ„ νƒμ μœΌλ‘œ μ ‘κ·Ό μ§€μ •μžλ₯Ό 포함할 수 μžˆμŠ΅λ‹ˆλ‹€.

abstract class Department {

    constructor(public name: string) {
    }

    printName(): void {
        console.log("Department name: " + this.name);
    }

    abstract printMeeting(): void; // λ°˜λ“œμ‹œ νŒŒμƒλœ ν΄λž˜μŠ€μ—μ„œ κ΅¬ν˜„λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.
}

class AccountingDepartment extends Department {

    constructor() {
        super("Accounting and Auditing"); // νŒŒμƒλœ 클래슀의 μƒμ„±μžλŠ” λ°˜λ“œμ‹œ super()λ₯Ό ν˜ΈμΆœν•΄μ•Ό ν•©λ‹ˆλ‹€.
    }

    printMeeting(): void {
        console.log("The Accounting Department meets each Monday at 10am.");
    }

    generateReports(): void {
        console.log("Generating accounting reports...");
    }
}

let department: Department; // 좔상 νƒ€μž…μ˜ 레퍼런슀λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€
department = new Department(); // 였λ₯˜: 좔상 ν΄λž˜μŠ€λŠ” μΈμŠ€ν„΄μŠ€ν™” ν•  수 μ—†μŠ΅λ‹ˆλ‹€
department = new AccountingDepartment(); // 좔상이 μ•„λ‹Œ ν•˜μœ„ 클래슀λ₯Ό μƒμ„±ν•˜κ³  ν• λ‹Ήν•©λ‹ˆλ‹€
department.printName();
department.printMeeting();
department.generateReports(); // 였λ₯˜: μ„ μ–Έλœ 좔상 νƒ€μž…μ— λ©”μ„œλ“œκ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€

κ³ κΈ‰ 기법 (Advanced Techniques)

μƒμ„±μž ν•¨μˆ˜ (Constructor functions)

TypeScriptμ—μ„œλŠ” 클래슀λ₯Ό μ„ μ–Έν•˜λ©΄ μ‹€μ œλ‘œ μ—¬λŸ¬ 개의 선언이 λ™μ‹œμ— μƒμ„±λ©λ‹ˆλ‹€. 첫 번째둜 클래슀의 μΈμŠ€ν„΄μŠ€ νƒ€μž…μž…λ‹ˆλ‹€.

class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}

let greeter: Greeter;
greeter = new Greeter("world");
console.log(greeter.greet()); // "Hello, world""

μ—¬κΈ°μ„œ let greeter: Greeter라고 ν•  λ•Œ, Greeter 클래슀의 μΈμŠ€ν„΄μŠ€ νƒ€μž…μœΌλ‘œ Greeterλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. 이것은 거의 λ‹€λ₯Έ 객체 지ν–₯ μ–Έμ–΄λ₯Ό μ‚¬μš©ν•˜λŠ” ν”„λ‘œκ·Έλž˜λ¨Έλ“€μ—κ² μžμ—°μŠ€λŸ¬μš΄ μ„±μ§ˆμž…λ‹ˆλ‹€.

λ˜ν•œ μƒμ„±μž ν•¨μˆ˜λΌκ³  λΆˆλ¦¬λŠ” 또 λ‹€λ₯Έ 값을 μƒμ„±ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. 이것은 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό new ν•  λ•Œ ν˜ΈμΆœλ˜λŠ” ν•¨μˆ˜μž…λ‹ˆλ‹€. μ‹€μ œλ‘œ μ–΄λ–»κ²Œ λ³΄μ΄λŠ”μ§€ ν™•μΈν•˜κΈ° μœ„ν•΄ μœ„μ˜ μ˜ˆμ œμ—μ„œ λ§Œλ“€μ–΄μ§„ JavaScriptλ₯Ό μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

let Greeter = (function () {
    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.prototype.greet = function () {
        return "Hello, " + this.greeting;
    };
    return Greeter;
})();

let greeter;
greeter = new Greeter("world");
console.log(greeter.greet()); // "Hello, world"

μ—¬κΈ°μ„œ, let GreeterλŠ” μƒμ„±μž ν•¨μˆ˜λ₯Ό 할당받을 κ²ƒμž…λ‹ˆλ‹€. newλ₯Ό ν˜ΈμΆœν•˜κ³  이 ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•  λ•Œ, 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό μ–»μŠ΅λ‹ˆλ‹€. λ˜ν•œ μƒμ„±μž ν•¨μˆ˜λŠ” 클래슀의 λͺ¨λ“  μ „μ—­ λ³€μˆ˜λ“€μ„ ν¬ν•¨ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. 각 클래슀λ₯Ό μƒκ°ν•˜λŠ” 또 λ‹€λ₯Έ 방법은 μΈμŠ€ν„΄μŠ€ μΈ‘λ©΄κ³Ό 정적 츑면이 μžˆλ‹€λŠ” 것 μž…λ‹ˆλ‹€.

이 차이λ₯Ό 보여주기 μœ„ν•΄ 예제λ₯Ό μˆ˜μ •ν•΄λ΄…μ‹œλ‹€.

class Greeter {
    static standardGreeting = "Hello, there";
    greeting: string;
    greet() {
        if (this.greeting) {
            return "Hello, " + this.greeting;
        }
        else {
            return Greeter.standardGreeting;
        }
    }
}

let greeter1: Greeter;
greeter1 = new Greeter();
console.log(greeter1.greet()); // "Hello, there"

let greeterMaker: typeof Greeter = Greeter;
greeterMaker.standardGreeting = "Hey there!";

let greeter2: Greeter = new greeterMaker();
console.log(greeter2.greet()); // "Hey there!"

이 μ˜ˆμ œμ—μ„œ greeter1은 이전과 λΉ„μŠ·ν•˜κ²Œ μž‘λ™ν•©λ‹ˆλ‹€. Greeter 클래슀λ₯Ό μΈμŠ€ν„΄μŠ€ν™”ν•˜κ³  이 객체λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. 이것은 전에 λ³Έ κ²ƒμž…λ‹ˆλ‹€.

λ‹€μŒμœΌλ‘œ, 클래슀λ₯Ό 직접 μ‚¬μš©ν•©λ‹ˆλ‹€. μ—¬κΈ°μ„œ greeterMakerλΌλŠ” μƒˆλ‘œμš΄ λ³€μˆ˜λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. 이 λ³€μˆ˜λŠ” 클래슀 자체λ₯Ό μœ μ§€ν•˜κ±°λ‚˜ μƒμ„±μž ν•¨μˆ˜λ₯Ό λ‹€λ₯΄κ²Œ μ„€λͺ…ν•©λ‹ˆλ‹€. μ—¬κΈ°μ„œ typeof Greeterλ₯Ό μ‚¬μš©ν•˜μ—¬ μΈμŠ€ν„΄μŠ€ νƒ€μž…μ΄ μ•„λ‹Œ "Greeter 클래슀 자체의 νƒ€μž…μ„ μ œκ³΅ν•©λ‹ˆλ‹€". ν˜Ήμ€ 더 μ •ν™•ν•˜κ²Œ μƒμ„±μž ν•¨μˆ˜μ˜ νƒ€μž…μΈ "GreeterλΌλŠ” μ‹¬λ³Όμ˜ νƒ€μž…μ„ μ œκ³΅ν•©λ‹ˆλ‹€". 이 νƒ€μž…μ€ Greeter 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“œλŠ” μƒμ„±μžμ™€ ν•¨κ»˜ Greeter의 λͺ¨λ“  정적 멀버λ₯Ό 포함할 κ²ƒμž…λ‹ˆλ‹€. greeterMaker에 newλ₯Ό μ‚¬μš©ν•¨μœΌλ‘œμ¨ Greeter의 μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜κ³  이전과 같이 ν˜ΈμΆœν•©λ‹ˆλ‹€.

μΈν„°νŽ˜μ΄μŠ€λ‘œμ¨ 클래슀 μ‚¬μš©ν•˜κΈ° (Using a class as an interface)

μ•žμ„œ μ–ΈκΈ‰ν•œ κ²ƒμ²˜λŸΌ, 클래슀 선언은 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ‚˜νƒ€λ‚΄λŠ” νƒ€μž…κ³Ό μƒμ„±μž ν•¨μˆ˜λΌλŠ” 두 가지λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. ν΄λž˜μŠ€λŠ” νƒ€μž…μ„ μƒμ„±ν•˜κΈ° λ•Œλ¬Έμ— μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•  수 μžˆλŠ” λ™μΌν•œ μœ„μΉ˜μ—μ„œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

class Point {
    x: number;
    y: number;
}

interface Point3d extends Point {
    z: number;
}

let point3d: Point3d = {x: 1, y: 2, z: 3};