typescript class
01. what are classes
object를 만드는 설계도
클래스 이전에 object를 방법은 function
javascript es6에서부터 class 키워드 사용가능 (접근제어자 부족...)
typescript에서는 클래스도 사용자가 만드는 타입중에 하나
02. Quick Start - class
기본 형태
class Person {}
const p1 = new Person();
console.log(p1)
tsconfig.json에서 target을 es5로 넣고, 컴파일해보면 class가 function으로 구현되어 있는걸 볼 수 있다.
"use strict";
var Person = /** @class */ (function () {
function Person() {
}
return Person;
}());
var p1 = new Person();
console.log(p1);
object가 만들어졌을 떄, 프로퍼티를 가지게 만들자.(consturctor 이용)
this를 사용하면 만들어진 object를 가르킬 수 있다.
class Person {
name:string;
constructor(name:string) {
this.name = name;
}
}
const p1 = new Person("Hong");
console.log(p1)
03. constructor & initialize
class Person {
name:string;
age:number;
}
const p1 = new Person();
Person class의 입장에서는 name과 age가 초기화된적이 없기때문에 에러가 난다.
각 변수에 값을 직접 넣어주거나, 초기화가 필요...
p1을 생성후에 나중에 값을 넣어줄때도 클래스 자체는 모른다.
하지만 이걸 의도적으로 표시해줄수 있는게 ! 이다. ! 를 쓸때는 주의해야된다.
class Person {
name:string = "Mark";
age!:number;
}
const p1 = new Person();
console.log(p1)
p1.age = 39
console.log(p1.age);
default 생성자도 있다. 별도의 생성자가 없으면 실행된다.
프로그래머가 construtor를 구현한다면,default생성자는 실행되지 않는다.
class Person {
name:string = "Mark";
age:number;
constructor(age:number) {
this.age = age
}
}
const p1 = new Person(29);
console.log(p1)
console.log(p1.age);
async를 지원하지 않는다.
04. 접근제어자(Access Modifiers)
기본적으로 모두 외부 접근 가능하다. (public)
class Person {
public name:string;
public age:number;
constructor(name:string, age:number) {
this.name = name;
this.age = age
}
}
const p1 = new Person("hong", 37);
private - 외부에서 접근 불가
class Person {
public name:string;
private age:number;
constructor(name:string, age:number) {
this.name = name;
this.age = age
}
}
const p1 = new Person("hong", 37);
// p1.age <---호출 안된다.
protected - 상속간에만 허용
05. initialization in constructor parameters
생성자의 파라미터에서 바로 초기화 하는 방법
constructor의 파라미터에 public을 붙이면 된다. (private, protected도 가능)
class Person {
// name:string;
// age:number;
constructor(public name:string, public age:number) {
// this.name = name;
// this.age = age;
}
}
const p1 = new Person("hong", 37);
p1.name
p1.age
06. Getters & Setters
이걸 이용해서 정보 조작을 막자
class Person {
constructor(private _name:string, private age:number) {}
get name() {
return this._name
}
set name(name:string) {
this._name = name
}
}
const p1 = new Person("hong", 37);
//프로퍼티처럼 실행
console.log(p1.name)
p1.name = "yeol"
console.log(p1.name)
07. readonly properties
readonly 키워드를 넣어서 읽기 전용 속성으로 만들자.
변경시에 에러를 보여준다.
프로퍼티 초기화에서는 가능(선언과 동시에 할당 , consturctor)
class Person {
public readonly name:string = 'Hong';
private readonly country:string = 'korea';
constructor(public _name:string, public age:number) {}
hello() {
//error - readonly
this.country = 'qwe'
}
}
const p1 = new Person("hong", 37);
//error - readonly
p1.name = 'yeol'
08. Index Signatures in class
동적으로 프로퍼티 이름이 바뀔 때, 고려해볼만한 기능
// class => object를 만들어내는 행위
// A반과 B반을 모두 나타낼 수 있는 객체
// {mark:'male', jade:'male'}
// {jenny:'female', alex:'male', anna:'female'}
class Students {
//mark:string = 'male'
//위에처럼 하면 동적으로 처리 불가
//index signatures 이용해서 동적 처리를 지원하자
//프로퍼티의 이름은 모르지만, 그게 가진 값은 string
[index:string]:string;
//좀 더 정확하게 하려면 "male", "female"만 가질수 있도록 union을 하면된다.
//프로퍼티의 이름은 모르지만, 그게 가진 값은 male 혹은 female
//[index:string]:"male"|"female";
}
const classA = new Students();
classA.mark = "male";
classA.jade = "male";
console.log(classA);
const classB = new Students();
classB.jenny = "female";
classB.anna = "female";
classB.alex = "male";
console.log(classB)
09. Static Properties & Methods
클래스간 공유이기때문에 한쪽에서 바뀌면 다른쪽도 영향을 받는다.
class Person {
public static CITY = "seoul";
public static hello() {
console.log('hello')
}
public change() {
Person.CITY = "suwon";
}
}
const p1 = new Person();
//static로 선언시 p1.CITY, p1.hello()로 사용할 수 없다.
//Person.hello() 이렇게 사용할 수 있다.
Person.hello();
console.log(Person.CITY); //seoul
p1.change();
console.log(Person.CITY); //suwon
10. Singletons
싱클톤이란..단 하나의 오브젝트만 가지고 논다.
class ClassNameA {}
const a = new ClassNameA()
const b = new ClassNameA()
//a와 b는 각각 다른 객체
//어디서든지 생성할 수 없게 막아아한다. private constructor이용
class ClassNameB {
//instance는 ClassNameB or null을 가질 수 있으므로..
private static instance:ClassNameB | null = null;
public static getInstance() : ClassNameB {
if (ClassNameB.instance === null) {
ClassNameB.instance = new ClassNameB()
}
return ClassNameB.instance;
//classNameB으로부터 만든 objecr가 있으면 그걸 리턴
//없으면 새로 만들어서 리턴
}
private constructor() {}
}
const c = ClassNameB.getInstance();
const d = ClassNameB.getInstance();
console.log(c === d); // true
11. 상속(Inheritance)
클래스가 다른 클래스를 가져다가 자신만의 기능을 추가 하는 것
class Parent {
//protected는 상속관계에서 접근 가능)
constructor(protected _name:string, private _age:number) {}
public print():void {
console.log(`name : ${this._name}, age : ${this._age}`);
}
}
//Parent는 new로 직접 생성도 가능
const p = new Parent('Hong', 37);
p.print()
class Children extends Parent {
public gender = "male";
constructor(age:number) {
//자식에서 constuctor을 사용할 경우 super를 이용해서 부모의 constructor을 호출해줘야한다.
//super를 맨 먼저 호출해줘야한다.
super("Yeol", age)
}
}
const c = new Children(5);
c.print()
12. Abstract Classes
완전하지 않은 클래스표현,
new를 이용해서 객체 생성 불가 -> 상속을 해서 완전한 클래스로 만들고 나서 사용해야된다.
abstract class AbstractPerson {
protected _name:string = "Mark";
abstract setName(name:string):void;
}
// new AbstractPerson() 불가...완전한 class가 아니다..
class Person extends AbstractPerson {
setName(name: string): void {
this._name = name
//throw new Error("Method not implemented.");
}
printName() {
console.log(this._name)
}
}
const p1 = new Person();
p1.setName("Hong")
p1.printName();