1. 오늘 배운 것
class
접근 제어자(private, public, protected)
이중 초기화 막기
readonly
super()
override
getter
setter
static
추상 클래스
싱글톤 패턴
2. class에 대한 공부
class 내부의 필드에 있는 변수들은 속성이라고 한다.
//TypeScript
//일반적으로 쓰이는 class
class Animal {
kind: string;
habitat: string;
constructor(kind: string, habitat: string){
this.kind = kind;
this.habitat = habitat;
}
printIntroduction(){
console.log('이 동물의 종류는 ' + this.kind + '입니다.');
console.log('그리고 서식지는 ' + this.habitat +'입니다.');
}
}
const cat = new Animal('mammalia', 'city');
//1. 생성자를 사용하고나서 객체의 함수 사용시
cat.printIntroduction();
//이 동물의 종류는 mammalia입니다.
//그리고 서식지는 city입니다.
//2. 객체의 속성을 인위적으로 바꿀 때
cat.kind = "feline";
cat.printIntroduction();
//이 동물의 종류는 feline입니다.
//그리고 서식지는 city입니다.
여기까지는 일반 클래스인데, 객체의 속성을 내 맘대로 바꿀 수가 있다.
이러면 팀 프로젝트 할 때, 일관성이 깨질 수도 있다.
//TypeScript
//접근 제어자, 이중 초기화를 막기, 상속, override(재정의)가 녹아있는 class
class Animal {
constructor(private kind: string, public habitat: string){
this.kind = kind;
this.habitat = habitat;
}
printIntroduction(){
console.log('이 동물의 종류는 ' + this.kind + '입니다.');
console.log('그리고 서식지는 ' + this.habitat +'입니다.');
}
}
class Cat extends Animal {
constructor(kind: string, habitat: string, public kindType: string){
//super()는 자식이 부모의 속성을 상속하고자 할 때 쓰는 것
super(kind, habitat);
}
//override
printIntroduction(){
//오류 발생!! this.kind를 접근 할 수 없다.
console.log('이 동물의 종류는 ' + this.kind + '입니다.');
console.log('그리고 서식지는 ' + this.habitat +'입니다.');
console.log('이 동물의 세부적인 종류는' + this.kindType + '입니다.' );
}
}
const cat = new Animal('mammalia', 'city');
//1. 생성자를 사용하고나서 객체의 함수 사용시
cat.printIntroduction();
//이 동물의 종류는 mammalia입니다.
//그리고 서식지는 city입니다.
//2. 객체의 속성을 인위적으로 바꿀 때 => kind 속성이 private이기때문에 이제 접근 못한다.
//오류는 걸려도 실행은 된다. 다만, 컴파일러는 감지하고 고치라고 할뿐
cat.kind = "feline";
cat.printIntroduction();
//이 동물의 종류는 mammalia입니다.
//그리고 서식지는 city입니다.
접근제어자에는 protected도 존재하는데, 이것을 사용한다면?
위의 코드에서 발생한 첫 번째 오류는 사라진다.
그리고 static 키워드를 사용하면 클래스와는 멀어진다.
그냥 일반 함수나 변수를 사용하는 느낌으로 바뀐다.
//TypeScript
//readonly, getter, setter, static 개념이 녹아 있는 class
class Animal {
static readonly livingPlanet = 'earth';
constructor(protected kind: string, public habitat: string){
this.kind = kind;
this.habitat = habitat;
}
get currentKind(){
if(this.kind){
return this.kind;
}
throw new Error('There is no kind');
}
set currentKind(kind: string){
if(!kind){
throw new Error('There is no parameter');
}
this.kind = kind;
}
printIntroduction(){
console.log('이 동물의 종류는 ' + this.kind + '입니다.');
console.log('그리고 서식지는 ' + this.habitat +'입니다.');
}
static printLivingPlanet(){
console.log("우리가 살고 있는 행성: " + this.livingPlanet);
}
}
class Cat extends Animal {
constructor(kind: string, habitat: string, public kindType: string){
super(kind, habitat);
}
//override
printIntroduction(){
//오류 해제!
console.log('이 동물의 종류는 ' + this.kind + '입니다.');
console.log('그리고 서식지는 ' + this.habitat +'입니다.');
console.log('이 동물의 세부적인 종류는' + this.kindType + '입니다.' );
}
}
const cat = new Cat('mammalia', 'city', '고양이과');
console.log(cat.currentKind);
cat.currentKind = '포유류';
console.log("현재 동물의 종류: " + cat.currentKind);
console.log(Cat.livingPlanet);
Cat.printLivingPlanet();
추상 클래스를 사용하려면, 먼저 추상 메소드를 사용해야한다.
1개 이상의 추상 메소드가 있다면, 추상 클래스로 사용할 수 있다.
내일 공부할 인터페이스와는 조금 차이가 있다.
인터페이스는 내의 속성들은 선언만 되었지, 값이 없다.
근데, 추상 클래스는 선언만 되어 있는 메소드가 있을 수도 있고,
선언과 할당 모두 되어있는 메소드가 있을 수 있다.
그러니 두 개념은 엄연히 다르다는 것을 알 수 있다.
//TypeScript
//추상 클래스 개념이 녹아 있는 class
//abstract 키워드 사용
abstract class Animal {
static readonly livingPlanet = 'earth';
constructor(protected kind: string, public habitat: string){
this.kind = kind;
this.habitat = habitat;
}
get currentKind(){
if(this.kind){
return this.kind;
}
throw new Error('There is no kind');
}
set currentKind(kind: string){
if(!kind){
throw new Error('There is no parameter');
}
this.kind = kind;
}
//abstract 키워드를 써야하며, 함수같은 경우는 이렇게 설정하자
abstract printIntroduction(): void;
static printLivingPlanet(){
console.log("우리가 살고 있는 행성: " + this.livingPlanet);
}
}
class Cat extends Animal {
constructor(kind: string, habitat: string, public kindType: string){
super(kind, habitat);
}
//override
printIntroduction(){
//오류 해제!
console.log('이 동물의 종류는 ' + this.kind + '입니다.');
console.log('그리고 서식지는 ' + this.habitat +'입니다.');
console.log('이 동물의 세부적인 종류는' + this.kindType + '입니다.' );
}
}
const cat = new Cat('mammalia', 'city', '고양이과');
cat.printIntroduction();
//TypeScript
//싱글톤 패턴의 개념이 녹아 있는 class
abstract class Animal {
static readonly livingPlanet = "earth";
constructor(protected kind: string, public habitat: string) {
this.kind = kind;
this.habitat = habitat;
}
get currentKind() {
if (this.kind) {
return this.kind;
}
throw new Error("There is no kind");
}
set currentKind(kind: string) {
if (!kind) {
throw new Error("There is no parameter");
}
this.kind = kind;
}
abstract printIntroduction(): void;
static printLivingPlanet() {
console.log("우리가 살고 있는 행성: " + this.livingPlanet);
}
}
class Cat extends Animal {
//꼭 이 클래스 타입에 대해서 외부에서 접근할 수 없지만, 생성자 없이도 접근 가능한 인스턴스 속성이 있어야한다.
private static instance: Cat;
//private 키워드 사용함으로써 이제 인스턴스는 하나로 고정이기 때문에 constructor은 접근 불가능하다.
private constructor(kind: string, habitat: string, public kindType: string) {
super(kind, habitat);
}
//외부에서 하나의 객체만 만드는 핵심적인 함수
static getInstance() {
if (Cat.instance) {
return this.instance;
}
return new Cat("포유류", "도시", "고양이과");
}
//override
printIntroduction() {
console.log("이 동물의 종류는 " + this.kind + "입니다.");
console.log("그리고 서식지는 " + this.habitat + "입니다.");
console.log("이 동물의 세부적인 종류는" + this.kindType + "입니다.");
}
}
const cat = Cat.getInstance();
cat.printIntroduction();
//44번줄에 대한 속성 값이 49번줄부터 51번줄 내용에 삽입되어 출력된다.
3. 느낀점
예전에 공부하던 class 개념을 다시 깨워주었다.
근데 class를 공부하다보면, this라는 개념과 prototype과 연관이 있을 수 밖에 없다.
한 번 공부하고, 글을 써야겠다.
그리고 typescript의 접근 제어자와 자바스크립트 접근 제어자는 생김세가 다르다.
처음엔 typescript의 접근 제어자를 봤을 때는 아 이거 자바스크립트에도 있었나 생각했다.
근데, 아니었다니...
'TIL' 카테고리의 다른 글
[TIL] 2022년 01월 6일 (0) | 2022.01.06 |
---|---|
[TIL] 2021년 12월 28일 (0) | 2021.12.28 |
[TIL] 2021년 12월 23일 (0) | 2021.12.23 |
[TIL] 2021년 12월 21일 (0) | 2021.12.21 |
[TIL] 2021년 12월 20일 (0) | 2021.12.20 |