한 걸음씩
[TypeScript] Class, Interface 본문
◆ 클래스
- 클래스는 객체를 생성하기 위한 템플릿으로서, 해당 클랙스로부터 생성된 객체를 인스턴스라고 한다
- 클래스를 사용하면 데이터와 해당 데이터에 대한 메서드를 하나로 묶어서 사용자 정이 타입을 생성할 수 있다
public(생략가능)
|
선언한 클래스 내, 상속받은 클래스 내, 인스턴스 모두 접근 가능
|
protected
|
선언한 클래스 내, 상속받은 클래스 내에서 접근 가능
|
private(#변수명)
|
선언한 클래스 내에서만 접근 가능
|
// TypeScript 코드
class Player{
constructor(
private firstName: string,
private lastName: string,
public nickName: string
){}
}
// nico라는 객체를 Player 클래스를 이용하여 생성
// nico는 Player 클래스의 인스턴스
// 인스턴스: 클래스를 기반으로 생성된 객체를 의미한다. 클래스를 통해 생성된 개별 객체를 인스턴스라고 한다
const nico = new Player('nico', 'las', '니꼬')
nico.nickName // public은 클래스 내부, 외부에서 접근할 수 있다
// 반면, private은 해당 클래스 내에서만 접근할 수 있다
// JavaScript 코드
"use strict";
class Player {
constructor(firstName, lastName, nickName) {
this.firstName = firstName;
this.lastName = lastName;
this.nickName = nickName;
}
}
const nico = new Player('nico', 'las', '니꼬');
nico.nickName;
// 접근제한자 - public, private, protected
class Car{
readonly name: string = 'car'
color: string
static wheels = 4
constructor(color: string, name: string){
this.color = color
this.name = name
}
start(){
console.log('start')
console.log(this.name)
console.log(Car.wheels)
}
}
class Bmw extends Car {
constructor(color: string, name: string){
super(color, name)
}
showName(){
console.log(super.name)
}
}
const z4 = new Bmw('black', '이름')
console.log(z4.name) // '이름'
console.log(Car.wheels) // 4
▷ abstract class
- 인스턴스를 직접 생성할 수 없는 클래스, 단순히 상속을 위해 사용되며, 자체적으로 객체를 생성할 수 없다.(new사용X)
- 추상 클래스를 상속받은 자식 클래스는 추상 메서드를 반드시 구현해야 하며, 구현이 없을 경우 컴파일 오류가 발생한다.
- 추상메서드를 선언할 때에는 메서드 이름 뒤에 'abstract' 키워드를 붙이고, 중괄호 대신 세미콜론으로 마무리한다
- 일반적으로 공통된 기능을 가진 클래스를 정의하고, 이를 상속받아 구체적인 동작으로 하는 클래스를 만들 때 사용된다.
- 코드의 재사용성과 유지보수성을 높일 수 있다.
- 추상 클래스는 다른 클래스가 상속받을 수 있는 클래스인데, 이 클래스는 직접 새로운 인스턴스를 만들 수 없다
- 자바스크립트로 확인해보면 그냥 클래스로 보여진다.
// 추상 클래스
abstract class Car{
color: string // color 프로퍼티
constructor(color: string){ // constructor 메서드 ; 객체 생성시 색상을 인자로 받아서 color프로퍼티 초기화
this.color = color
}
start(){ // start 메서드 ; 'start' 문자열을 출력하는 기본 구현
console.log('start')
}
// doSomething()메서드가 추상 메서드로 선언되어 있으므로 Car 클래스를 상속받은 하위 클래스에서 반드시 구현해야 한다
abstract doSomething(): void // 추상 메서드이므로 실제 동작 구현이 없음
}
// 추상 클래스는 반드시 상속받아서 사용해야 한다
// Bmw는 Car 클래스를 상속받은 하위 클래스, doSomething 메서드를 구현
class Bmw extends Car {
constructor(color: string){
super(color)
}
doSomething(){
alert(3) // 호출 -> Car클래스의 추상성 해소, 실제로 동작하는 클래스를 만듦
}
}
const z4 = new Bmw('black') // Bmw 클래스를 인스턴스화하여 z4변수에 할당
// z4변수는 Bmw 클래스의 인스턴스가 된다
// z4변수는 Car 추상 클래스로부터 상속된 color 프로퍼티와 start메서드를 가지고 있고
// Bmw 클래스에서 구현한 doSomething 메서드도 가지고 있다
⊙ 추상 메소드
- 추상 클래스 안에 들어간 추상 메소드 : 클래스 안에서 구현하지 않으면 됨
- 추상 메소드: 추상 클래스를 상속받는 모든 것들이 구현을 해야하는 메소드를 의미
- 메소드: 클래스 안에 존재하는 함수
◆ 인터페이스
let user:object
user={
name:'xx',
age: 30
}
// user가 object타입이지만, name, age의 타입이 명시되지 않았기 때문에 오류 발생
console.log(user.name)
▷ interface
- 클래스가 어떤 프로퍼티와 메서드를 가져야 하는지를 정의하는 일종의 '계약서'
- 인터페이스는 클래스가 반드시 구현해야 하는 멤버(프로퍼티, 메서드)들의 목록을 제공한다
- 인터페이스 자체로는 구현이 이루어지지 않으며, 단지 클래스가 따라야 하는 규칙들을 명시하는 역할을 한다
- 자바스크립트로 컴파일되지 않는다!!
- type, interface는 오브젝트의 모양과 타입을 알려주는 같은 목표를 가졌지만, type은 상속할 때 또 다른 타입을 만들어야한다. interface는 상속할 때 객체 지향 프로그래밍과 같은데 extends를 사용한다. interface는 이후에 타입을 추가할 때 다시 선언하여 사용할 수 있다. 반면 type은 같은 변수를 가진채 타입을 추가하면 duplicate되어 에러가 발생한다.
- type은 객체 뿐만 아니라 다양한 데이터 타입을 정의하는 데 사용된다
- interface는 객체의 구조와 형태를 정의하는 데 주로 사용된다.
type Score = 'A' | 'B' | 'C' | 'D'
interface User{
name:string,
age:number,
// '?' : 선택
gender?:string
// readonly 속성은 읽기만 가능! 수정X
readonly birthYear : number
// number를 key로, string을 value로
// Score에 없는 것들을 사용 불가
[grade:number] : Score
}
let user:User={
name:'xx',
age:10,
birthYear : 2000,
1 : 'A',
2 : 'B'
}
// 값을 변경할 수 있음
user.age = 20
// 값을 추가할 수 있음
user.gender = 'male'
console.log(user.name) // 'xx'
// Add함수의 타입은 number
interface Add{
(num1:number, num2:number):number
}
const add:Add = function(x, y){
return x + y
}
add(10, 20) // 30
// IsAdult함수의 타입은 boolean
interface IsAdult {
(age:number):boolean
}
const a:IsAdult = (age) =>{
return age > 19
}
a(40) // true
▷ implement
- 클래스가 특정 인터페이스를 구현한다는 것을 나타내는 역할을 한다
- 클래스가 인터페이스의 모든 멤버를 반드시 구현해야 함을 의미하는 것이다
▷ class
- 객체를 생성하기 위한 설계도 또는 템플릿으로, 객체 지향 프로그래밍에서 데이터와 해당 데이터에 관련된 동작(메서드)을 하나로 묶는 데 사용된다.
- 클래스는 객체의 속성(프로퍼티)과 동작(메서드)를 정의하는 멤버들로 구성된다
- 객체는 클래스를 기반으로 생성되며, 생성된 객체를 클래스의 인스턴스라고 한다.
▷ constructor
- 생성자
- 클래스의 인스턴스를 초기화하는 특별한 메서드
- 클래스로부터 객체를 생성할 때, 생성자가 호출되어 객체의 초기 상태를 설정한다.
- 생성자는 클래스의 이름과 동일한 이름을 가지며, constructor 키워드를 사용하여 정의한다.
- 생성자는 객체가 생성될 때 자동으로 호출되므로, 객체를 생성할 때 필요한 초기화 작업을 수행하는 데 사용된다.
▷ instance
- 클래스의 구조를 바탕으로 실제로 메모리에 할당된 객체
- 클래스는 템플릿이고, 인스턴스는 이 템플릿을 기반으로 만들어진 객체
- 인스턴스는 클래스의 구조대로 생성되기 때문에 클래스에서 정의한 변수(프로퍼티)와 메서드를 모두 가질 수 있다
- 클래스의 구조에 따라 동작하며, 각각의 인스턴스는 서로 독립적으로 동작한다.
- Bmw클래스는 color, wheels 프로퍼티와 start() 메서드를 가지고 있다. Bmw클래스의 인스턴스를 생성하면 해당 인스턴스는 color, wheels 프로퍼티를 가지고 있고, start()메서드를 호출할 수 있다.
interface Car{
// 프로퍼티
color:string
wheels:number
// 메서드
start():void
}
// Car 인터페이스를 implement키워드를 사용하여 Bmw 클래스 구현
// -> color, wheels, start 메서드를 반드시 구현해야 함
class Bmw implements Car{
color;
wheels = 4
// Bmw 클래스의 생성자는 c라는 매개변수를 받아서 color 프로퍼티에 값을 할당하는 역할을 수행하고 있음
constructor(c:string){
// 생성자 내에서 객체의 프로퍼티에 값을 할당
// this.color는 color 프로퍼티를 의미
this.color = c
}
start(){
console.log('go...')
}
}
// 생성자는 new 키워드와 함께 클래스를 인스턴스화할 때 자동으로 호출
// b변수는 Bmw 클래스의 인스턴스이며, 이 인스턴스는 color, wheels, start() 메서드를 가지고 있다
const b = new Bmw('green')
console.log(b)
// Bmw: {
// "wheels": 4,
// "color": "green"
// }
wheels 프로퍼티는 클래스 내에서 직접 초기값을 지정했는데 이런 방법은 정적으로 값을 할당하는 방법이기 때문에 클래스가 인스턴스화될 때마다 항상 동일한 초기값을 가지게 된다. 이 경우에 객체가 생성될 때마다 다른 초기값을 제공할 수 없기 때문에 유연성이 떨어진다.
반면에, color 프로퍼티는 생성자 내에서 초기값을 지정했는데, 외부에서 객체를 생성할 때 매개변수를 통해 다양한 초기값을 전달할 수 있다. 이렇게 하면 같은 클래스의 인스턴스라도 각각 다른 초기값을 가질 수 있으며, 이를 통해 객체의 다양한 상태를 표현하고 다양한 상황에 유연하게 대처할 수 있다.
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
// 외부에서 Person 클래스의 생성자를 호출하여 객체 생성
const person1 = new Person("Alice", 30);
const person2 = new Person("Bob", 25);
console.log(person1); // Person { name: 'Alice', age: 30 }
console.log(person2); // Person { name: 'Bob', age: 25 }
▷ extends
- 클래스 간 상속을 구현하는 키워드
- 이미 존재하는 클래스를 기반으로 새로운 클래스를 만들 때 사용
- 상속을 통해 기존 클래스의 프로퍼티와 메서드를 재사용하고, 새로운 기능을 추가하거나 기존 기능을 변경할 수 있다
- extends 키워드를 사용하여 클래스 상속을 구현할 때, 하위 클래스는 상위 클래스의 모든 멤버를 상속받게 된다.
- 하위 클래스는 상위 클래스의 멤버를 사용하거나 오버라이딩(재정의)하여 자신만의 동작을 구현할 수 있다
// 상위 클래스 (부모 클래스)
class Animal {
constructor(public name: string) {}
// 메서드
makeSound() {
console.log("Animal makes a sound");
}
}
// 하위 클래스 (자식 클래스)
class Dog extends Animal {
constructor(name: string) {
super(name); // 상위 클래스의 생성자 호출
}
// 오버라이딩: 상위 클래스의 메서드를 재정의
makeSound() {
console.log("Dog barks");
}
// 자식 클래스의 메서드
fetch() {
console.log("Dog fetches a ball");
}
}
// 하위 클래스의 인스턴스 생성
const myDog = new Dog("Buddy");
console.log(myDog.name); // "Buddy"
myDog.makeSound(); // "Dog barks"
myDog.fetch(); // "Dog fetches a ball"
interface Car{
color: string
wheels:number
start():void
}
interface Toy{
name:string
}
interface ToyCar extends Car, Toy{
price:number
}
◆ 참고 공식 문서
https://www.typescriptlang.org/docs/handbook/interfaces.html
Handbook - Interfaces
How to write an interface with TypeScript
www.typescriptlang.org
https://www.typescriptlang.org/docs/handbook/classes.html
Handbook - Classes
How classes work in TypeScript
www.typescriptlang.org
2023.08.05 - [TypeScript] - [TypeScript] class, interface 연습문제
'TypeScript' 카테고리의 다른 글
[TypeScript] class, interface 연습문제 (0) | 2023.08.05 |
---|---|
[TypeScript] 함수 연습 문제 function, call signatures, generic (0) | 2023.08.03 |
[TypeScript] Functions (0) | 2023.08.03 |
[TypeScript] Type (0) | 2023.08.03 |
[TypeScript] 리터럴, 유니온/교차 타입, 제네릭, 유틸리티 타입 (0) | 2023.07.26 |