먼저 비교를 위해 Javascript에서 class를 사용하는 방법에 대해 알아보겠습니다
//방법1
const User=function(name,age){
this.name=name;
this.age=age;
this.showName=fuction(){
console.log(this.name)
}
}
const mike= new User("Mike",30)
//방법2
class User2{
constructor(name,age){
this.name=name;
this.age=age;
}
showName(){
console.log(this.name)
}
}
const tom=new User2("tom",10)
class Car{
constructor(color){
this.color=color
this.wheels=4
}
drive(){
console.log("drive..")}
stop(){
console.log("stop!")}
}
//확장
class bmw extends Car{
constructor(color){
super(color)
//class의 constructor는 빈객체를 만들어주고 this로 빈객체를 pointing한다
// extends는 super키워드로 부모클래스에 constructor를 실행해주 어야한다
//z4에 color값을 부모클래스와 동일하게 받기위해서는 자식에게도 똑 같이 인자값을 넣어주어야한다
this.navigation=1;
}
park(){
console.log("Park")
}
stop(){
console.log("OFF") //위에 stop을 오버라이딩한다, "OFF"출력
super.stop()
//부모메소드를 그대로 쓰면서 확장하고 싶다면 super키워드사용
//부모메소드 "stop!"출력
}
}
const z4=new bmw("blue")
ts에서 class를 작성할때는 맴버변수를 미리 선언해주어야한다
단, 접근 제한자(Access modifier)를 사용하면 맴버변수 없이 가능- public, private,protected
정적맴버변수를 만들 수 있다
static으로 선언된 정적 맴버변수나 메서드는 this를 쓰는게 아니라 class명을 써서 불러야한다
class Car {
//맴버변수 미리 선언해주어야한다
name: string = 'car';
color: string;
static wheels=4
//생성자 정의
constructor(color: string) {
this.color = color;
}
//메서드 정의
start() {
console.log('start');
console.log(this.name);
console.log(Car.wheels)
}
}
//Extends
class Bmw extends Car {
constructor(color: string) {
super(color);
}
showName() {
console.log(this.name);
}
}
//클래스의 인스턴스 생성
const z4 = new Bmw('red');
console.log(z4);
console.log(Car.wheels) //static은 class명으로 통해 불러온다
앞에 abstract를 붙여서 만들어준다
new를 통해서 객체를 만들수없고 상속을 통해서만 사용이 가능하다
사용이유는 프로퍼티나 메소드에 이름만 선언해주고 구체적인 기능은 상속받는 쪽에서 구현하기 위한 것
abstract class Car {
color: string;
constructor(color: string) {
this.color = color;
}
abstract doSomething():void
}
class Bmw extends Car {
constructor(color: string) {
super(color);
}
doSomething(): void {
alert(3)
}
}
const z4 = new Bmw('red');
//interface에서 제네릭 사용
interface Mobile<T>{
name:string;
price:number;
option:T;
}
const m1:Mobile<object>={
name:"s21",
price:1000,
option:{
color:"red",
coupon:"good"
}
}
const m2:Mobile<string>={
name:"s20",
price:900,
option:"good"
}
interface User{
id:number;
name:string;
age:number
gender:"m"|"f"
}
type UserKey=keyof User; // "id" | "name" | "age" | "gender"
const uk:UserKey="name"
<T>
프로퍼티를 모두 옵션으로 바꿔준다
interface User{
id:number;
name:string;
age:number
gender:"m"|"f"
}
//Partial을 사용하게되면
interface User{
id?:number;
name?:string;
age?:number
gender?:"m"|"f"
}
//와 같아지는 것
let admin:Partial<User>={
id:1,
name:"Bob",
}
<T>
Partial과 반대로 Required는 모든 interface가 필수로 요구된다
interface User{
id:number;
name:string;
age?:number
}
//위 3가지 변수를 필수로 받아야 에러가 뜨지 않는다
let admin:Required<User>={
id:1,
name:"Bob",
age:30
}
<T>
홈에 할당만 가능하고 뒤에 수정은 불가능해진다
속성에 접근하여 값을 읽거나, 쓰기위한 Getter,Setter함수를 사용하여 속성을 정의
getter - 속성값을 검색 (속성을 반환)
setter - 특정 유효성 검사나 작업을 통해 속성값을 수정(속성에 값을 할당하기 전에 유효성 검사)
궁금증??
getter와 setter을 사용하는 이유는 클래스 내부의 속성을 보호하고 , 속성에 접근할때 추가적인 로직을 수행하기 위해 사용한다
그러면 ts는 왠만하면 private로 만들어서 내부 로직을 보호하고 get과 set으로 꺼내쓰는 것이 좋은 코드인가?
chat-GPT 왈!
일반적으로 TypeScript에서 클래스의 속성을 private로 선언하여 외부에서 직접적인 접근을 막고, getter와 setter를 통해 간접적인 접근을 허용하는 것이 좋은 설계 방법
이러한 방법은 객체지향프로그래밍의 핵삼 개념인 캡슐화를 따르는 것
class에서 static을 사용해서 만들기 vs 그냥 함수형으로 사용해서 만들기