object를 만드는 blueprint
클래스 이전에 object를 만드는 기본적인 방법은 function 이다.
TS에서 클래스는 사용자가 만드는 타입의 하나라고 볼 수 있다.
class Person {} //가장 간단한 형태
const p1 = new Person(); //p1 === object
class Person2 {
name;
constructor(name: string) {
this.name = name;
}
}
const p2 = new Person('lala');
class
키워드를 사용해 클래스를 만든다. 이름은 보통 대문자로 작성한다.
new
를 이용하여 class를 통해 object를 만들 수 있다.
constructor를 이용해 object를 생성하면서 값을 전달할 수 있다.
this를 이용해 만들어진 object를 가리킬 수 있다.
JS로 컴파일 되면 es5에서는 function으로 변경된다. (es6에서는 class로)
class Person {
name: string; //이렇게만 작성할 시 초기화가 되지 않아 에러가 발생한다. strict
age!: number;
}
//니중에 런타임 상에서 할당되어도 아직은 모름
//! 를 써서 나중에 할당될 것이라는 것을 알려줄 수도 있다.
const p2 = new Person('lala');
생성자 함수가 없으면 디폴트 생성자가 불린다.
strict 모드에서는 프로퍼티를 선언하는 곳 또는 생성자에서 값을 할당해야한다.
name: string = "mark"
constructor(name: string) { this.name = "mark" } )
이러지 않을거면 !를 붙여서 표현한다. (런타임 상에서 할당될 것이라는 뜻)
클래스의 프로퍼티가 정의 되어 있지만, 값을 대입하지 않으면 undefined이다.
생성자에는 async 설정할 수 없다.
public, private, protected
private 는 클래스 내부에서만 접근이 가능해진다.
private 변수 앞에 언더바를 써주면서 private라는 것을 알려주기도 했었다. 습관적으로 쓰기도 함.
class Person {
public name: string = 'mark';
public age!: number;
public constructor(age?: number) {
if( age === undefined) {
this.age = 20;
} else{
this.age = age;
}
public asyn init() {}
}
class Person {
public constructor(public name: string, public age: number) {}
}
const p1: Person = new Person('mark', 33);
생성자 매개변수에 접근 제어자를 명시해주면 위에 속성으로 적어주지 않아도 된다.
class Person {
public constructor(public name: string, public age: number) {}
}
const p1: Person = new Person('mark', 33);
console.log(p1.name); //get 가져오기
p1.name = 'lala'; //set 집어넣기
이렇게 get을 하는 함수는 getter
, set을 하는 함수는 setter
라고 부른다.
class Person {
public constructor(private _name: string, private _age: number) {}
get name() { //getter
return this._name; //가져오는 것이니까 return 꼭 필요
}
set name(n: string) { //setter
this._name = n;
}
}
const p1: Person = new Person('mark', 33);
console.log(p1.name); //getter 실행한 것
p1.name = 'lala'; //setter 실행한 것
class Person {
public readonly name: string = 'mark'; //여기에 set 못한다.
private readonly country: string = 'korea'; //이 안에서도 수정 불가
public constructor(private _name: string, private _age: number) {}
get name() {
return this._name;
}
}
const p1: Person = new Person('mark', 33);
console.log(p1.name);
p1.name = 'lala'; //에러 발생
readonly
가 달려있는 경우 public이든 private이든 바꿀 수 없다.
class -> object를 만들어내는 것
class Students {
[index:string]: "male" | "female"
//index는 있을 수도 있고 없을 수도 있어서 초기화 필요 없다.
}
const a = new Students();
a.mark = 'male';
a.lala = 'female';
const b = new Students();
b.mimi = 'female';
b.jeno = 'male';
b.lili = 'female';
동적으로 바뀌는 기능이다 라고 생각하자.
class Person {
private static CITY = 'seoul';
public static hello() { //static!!!
console.log('hello', Person.CITY);
}
}
Person.hello(); //static 메소드 때문에 가능하다.
중간 매체를 통해서 object 만들기.
class ClassName {
private static instance: ClassName | null = null;
public static getInstance() {
//ClassName 으로부터 만든 object 있으면 그것을 리턴하고
// 없으면 새로 만든다
if (ClassName.instance === null) {
ClassName.instance = new ClassName();
}
return ClassName.instance;
}
const a = ClassName();
const b = ClassName();
//이렇게 하면 a와 b는 같다.
class Parent {
constructor(protected _name: string, private _age: number) {}
public print(): void {
console.log(`이름은 ${this.name} 이고, 나이는 ${this.age} 이다.`);
}
}
class Child extends Parent {
public name = 'lalal'; //override 가능
public gender = 'male';
constructor(age: number) { //자식만의 생성자 가능하나
//super를 사용해서 부모의 생성자도 명시해주어야함
super('lalal', age)
}
}
const p = new Parent('mark', 33);
상속 받은 Child 가 아무것도 없으면 부모의 생성자 그대로 받는다.
abstract class AbstractPerson {
protected _name: string = 'mark';
abstract setName(name: string): void;
}
class Person extends AbstractPerson {
setName(name: string): void {
this._name = name;
}
}
const p = new Person();
완전하지 않은 class를 abstract
를 사용하면 표현할 수 있다.
기능이 완전하지 않아서 new
로 무언가 할 수 없다.
그래서 이 완전하지 않은 클래스를 상속 받아서 기능을 완전하게 만들어줄 수 있다.