본문 바로가기

TypeScript/Handbook

[TypeScript] 04. Classes

원문: https://www.typescriptlang.org/docs/handbook/classes.html


 ES6 이전에 javascript 에서는 재사용 가능한 콤포넌트를 만들기 위해 펑선과 프로토타입을 사용했다. 하지만 ES6 이후 javascript 개발자들은 클래스 기반의 객체지향 프로그래밍 처럼개발을 할 수 있게 되었다. 타입스크립트는 이러한 기술들을 브라우저가 ES6를 지원하던 안하던 가능하게 해준다.


Classes

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

let greeter = new Greeter("world");

 문법은 java나 C#과 유사하다. greeting 이라는 속성(property)과, 생성자(constructor), 그리고 greet이라는 함수(method)를가지는 Greeter라는 클래스를 정의했다.

 클래스 내부에 정의된 값이나 함수에 접근하기 위해서는 this 키워드를 이용하여 접근한다.

 마지막 라인에서 보듯이 new 키워드를 이용하여 사전에 정의한 constructor를 호출 함으로써 Greeter 클래스의 새로운 object를 생성 할 수 있다.


Inheritance

 typescript를 이용해 oop 패턴을 이용 할 수 있다. 클래스 기반 프로그래밍의 기본이되는 상속 역시 사용 가능하다. 예를 보자

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 키워드를 이용한다.

 위 예제에서는 Snake와 Horse 클래스가 Animal 클래스를 상속 받음으로서 Animal 클래스가 가지고 있는 속성이나, 함수를 사용할 수 있게 되었다. 자식 클래스의 생성자 에서는 반드시 "super()" 구문을 이용하여 부모 클래스의 생성자를 실행 해야 하며, 부모 클래스의 함수를 오버라이딩 하는 경우 다른 언어들과 마찬가지로 부모 클래스와 동일한 함수명을 이용하여 함수를 재 정의(오버라이딩) 하여 사용 할 수 있다.


Public, private, and protected modifiers

- public by default

 typescript에서 한정어를 정의하지 않으면 public 으로 정의되어 어디서나 접근 가능하다.

- Understanding private

 private 으로 선언된 변수는 class 밖에서 접근 할 수 없다.

- Understanding protected

 protected로 선언된 변수는 자기 class 또는 자기를 상속받은 class에서만 접근이 가능하다.


Readonly modifier

 readonly 키워드를 이용해서 읽기 전용 속성값들(properties)을 만들 수 있다. 읽기 전용 속성값들은 선언 될때 값을 초기 화하거나, 생성자에서 초기화 해야 한다.

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"; // error! name is readonly.

- Parameter properties

 생성자 매개변수에 한정어(public, protected, private)나 readonly 를 이용하여 클래스의 속성값으로 정의 할 수 있다.

class Octopus {
    constructor(readonly name: string, private age: number) {
    }
}

//위 코드는 아래 코드와 동일하다.

class Octopus {
    readonly name: string;
    private age: number;
    constructor(_name: string, _age: number) {
        this.name = _name;
        this.age = _age;
    }
}


Accessors

 typesscript setter와 getter를 지원한다. 예를 보자

class Employee {
    private _fullName: string;

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

    set fullName(newName: string) {
        if (passcode && passcode == "secret passcode") {
            this._fullName = newName;
        }
        else {
            console.log("Error: Unauthorized update of employee!");
        }
    }
}

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

 setter와 getter를 위와 같은 형태로 구현 할 수 있다.


Static Properties

 static 키워드를 이용하여 class의 static 변수(인스턴스를 생성하지 않아도 사용할 수 있는 변수)를 선언 할 수 있다.

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}));

위 예제에서 static 으로 선언된 origin object는 instance를 생성하지 않아도 Grid.origin 으로 접근 할 수 있게 되었다.


Abstract Classes

 abstract 클래스는 지금 당장 구현하지 않아도 되는 abstract method를 가질 수 있다.

 abstract class 만으로는 인스턴스를 생성 할 수 없고, 반드시 이를 상속받은 자식 클래스가 abstract method를 구현한 후 생성 할 수 있다. interface와 비슷 하지만, abstract class는 구현된 함수(abstract method 가 아닌 일반 method)를 가질 수 있다.

abstract class Department {

    constructor(public name: string) {
    }

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

    abstract printMeeting(): void; // must be implemented in derived classes
}

class AccountingDepartment extends Department {

    constructor() {
        super("Accounting and Auditing"); // constructors in derived classes must call super()
    }

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

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

let department: Department; // ok to create a reference to an abstract type
department = new Department(); // error: cannot create an instance of an abstract class
department = new AccountingDepartment(); // ok to create and assign a non-abstract subclass
department.printName();
department.printMeeting();
department.generateReports(); // error: method doesn't exist on declared abstract type


Advanced Techniques


 설명이 귀찮네요...

- Constructor functions

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());

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

let greeter2: Greeter = new greeterMaker();
console.log(greeter2.greet());


- 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};



반응형

'TypeScript > Handbook' 카테고리의 다른 글

[TypeScript] 06. Generics  (0) 2018.10.23
[TypeScript] 05. Functions  (0) 2018.01.31
[TypeScript] 03. Interfaces  (0) 2017.05.04
[TypeScript] 02. 변수 선언  (0) 2017.04.25
[TypeScript] 01. Basic Types  (0) 2017.04.24