[TIL] Class

·2023년 10월 20일
0

TIL

목록 보기
11/85
post-thumbnail

클래스

  • '클래스' 란? : 객체를 생성하기 위한 일종의 템플릿!
    • 책상을 만들기 위한 설계도
    • LIKE 붕어빵을 만들기 위한 붕어빵 틀
  • '인스턴스' 란? : 클래스를 통해 만들어진 실제 객채들!
    • 설계도를 보고 만들어진 실제 책상
    • LIKE 붕어빵 틀로 만들어진 붕어빵들 🥐

Class / Constructor

class Person {
	// 생성자
  constructor(name, age) {
    // new라는 키워드를 이용해서 인스턴스를 만들 때, 기본적으로 넣어야 하는 값들을 의미해요! :)
	// 여기서 말하는 this는 (미래에 생성할) 인스턴스를 의미한다!
    this.name = name;
    this.age = age;
  }

	// 다양한 메소드를 아래와 같이 정의할 수 있어요.
	// 여기서 this.name으로 내부 값을 접근해야 한다!
  sayHello() {
    console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
  }
}

const person1 = new Person("Alice", 30);
const person2 = new Person("Bob", 25);

// 만든 객체를 토대로 메서드 호출해보기
person1.sayHello(); // "Hello, my name is Alice and I am 30 years old."
person2.sayHello(); // "Hello, my name is Bob and I am 25 years old."
  • 클래스를 생성하기 위해스는 class 라는 키워드를 사용한다.
  • constructor는 클래스의 생성자 함수이다. 생성자 함수는 객체를 생성할 때 호출되며, 객체를 초기화하는 역할을 한다.

Getter / Setter

  • getter 는 속성 값을 반환하는 메서드.
  • setter 는 속성 값을 설정하는 메서드. (입력값에 대한 유효성 검사 시 주로 사용)
  • 이를 통해 생성한 인스턴스를 정해진 규격 안에서 변경할 수 있다!
class Rectangle {
  constructor(height, width) {
    // underscore : private(은밀하고, 감춰야 할 때)
    // this로 접근하는 property에 underscore(_)를 사용하자.
    this._height = height;
    this._width = width;
  }

  // width를 위한 getter
  get width() {
    return this._width;
  }

  // width를 위한 setter
  set width(value) {
    // 검증 1 : value가 음수이면 오류!
    if (value <= 0) {
      console.log("[오류] 가로길이는 0보다 커야 합니다!");
      return;
    } else if (typeof value !== "number") {
      console.log("[오류] 가로길이로 입력된 값이 숫자타입이 아닙니다!");
      return;
    }
    this._width = value;
  }

  // height를 위한 getter
  get height() {
    return this._height;
  }

  // height를 위한 setter
  // understore(_)![](https://velog.velcdn.com/images/hw1635/post/85e58570-3f6e-40e0-9931-6f8c8172c06c/image.png)
를 쓰지 않으면 무한루프에 빠져서 콜스택이 꽉차게 된다!
  set height(value) {
    // 검증 1 : value가 음수이면 오류!
    if (value <= 0) {
      console.log("[오류] 세로길이는 0보다 커야 합니다!");
      return;
    } else if (typeof value !== "number") {
      console.log("[오류] 세로길이로 입력된 값이 숫자타입이 아닙니다!");
      return;
    }
    this._height = value;
  }

  // getArea : 가로 * 세로 => 넓이
  getArea() {
    const area = this._width * this._height;
    console.log(`넓이는 => ${area}입니다.`);
  }
}

// instance 생성
const rect1 = new Rectangle(10, 7);
rect1.getArea(); // 넓이는 => 70입니다.
const rect2 = new Rectangle(10, 30);
rect2.getArea(); // 넓이는 => 300입니다.
  • this 로 접근하는 property 에 underscore(_) 를 사용하여 구분하지 않았을 경우 setter와 getter에서 무한루프에 빠지게 된다.

상속 (Inheritance)

  • 클래스는 상속을 통해 다른 클래스의 기능을 물려받을 수 있다.
  • 상속을 하는 클래스 : super class 또는 base class
  • 상속을 받는 클래스 : sub class
class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}

// 동물 클래스를 상속받는 Dog 클래스를 만든다!
class Dog extends Animal {
  // 상속받을 때, speak()를 입맛에 맞게 재정의할 수 있다. 이를 overrinding 이라고 한다!
  speak() {
    console.log(`${this.name} barks.`);
  }
}

// Dog를 만들 때는 Animal의 상속을 받은 class이기 때문에 이름을 필수로 받아야 한다!
let dog = new Dog("cutie");

// speak는 'makes a noise'가 아니라, 'barks'가 출력된다.
dog.speak(); // "cutie barks."
  • 상속을 통해 클래스를 확장하려면 extends 키워드를 사용하여 상속받을 클래스를 정의한다.
// 새로운 Car class 정의
class Car {
  constructor(modelName, modelYear, type, price) {
    this.modelName = modelName;
    this.modelYear = modelYear;
    this.type = type;
    this.price = price;
  }
  // 클락션을 울리는 메서드
  makeNoise() {
    console.log(`${this.modelYear}에 생산된 ${this.modelName}: 빵!`);
  }
}

class ElectronicCar extends Car {
  // 재정의가 필요하다면 서브 클래스에도 ㅇconstructor 써주어야 한다.
  constructor(modelName, modelYear, price, chargeTime) {
    // Car (부모 클래스) 에도 알려주기!
    // 부모와 자식의 constructor가 다르기 때문에 맞춰주기 위해 super 키워드 사용
    super(modelName, modelYear, "e", price);
    this._chargeTime = chargeTime;
  }
}
// 자동차 만들기
const car1 = new Car("Sorento", "2023", "h", 5000);
const car2 = new Car("SM5", "1999", "g", 3000);
car1.makeNoise(); // 2023에 생산된 Sorento: 빵!
car2.makeNoise(); // 1999에 생산된 SM5: 빵!
// 전기 자동차 만들기
const eleCar1 = new ElectronicCar("tesla", "2023", 9000, "60min");
eleCar1.makeNoise(); // 2023에 생산된 tesla: 빵!
eleCar1.chargeTime = "20min";
console.log(eleCar1.chargeTime); // 20min

super

  • super를 호출하면 부모 클래스의 constructor를 호출한다.
  • 인스턴스 초기화를 위해 전달한 인수는 수퍼클래스와 서브클래스에 배분되고 상속 관계의 두 클래스는 서로 협력하여 인스턴스를 생성한다.

💡 [ super 호출 시 주의사항]

  • 서브 클래스에서 constructor를 생략하지 않는 경우 서브클래스의 constructor에서는 반드시 super를 호출해야 한다.
  • 서브클래스의 constructor에서 super를 호출하기 전에는 this를 참조할 수 없다.
  • super는 반드시 서브클래스의 constructor에서만 호출한다. 서브클래스가 아닌 클래스의 constructor나 함수에서 super를 호출하면 에러가 발생한다.

정적 메서드 (Static Method)

  • 정적메서드는 인스턴스를 생성하지 않아도 호출할 수 있는 메서드를 말한다.
  • 정적메서드는 클래스로 호출된다.
  • 정적메서드는 인스턴스 없이도 호출할 수 있다.
class Calculator {
  static add(a, b) {
    return a + b;
  }

  static subtract(a, b) {
    return a - b;
  }
}

console.log(Calculator.add(1, 2)); // 3
console.log(Calculator.subtract(3, 2)); // 1
  • 클래스에스는 static 이라는 키워드를 사용하여 클래스 레벨의 메서드를 정의할 수 있다.
  • 클래스 레벨의 메서드는 인스턴스에서 호출할 수 없으며 클래스 이름으로 직접 호출한다.
  • 인스턴스를 만들지 않고 사용할 수 있기 때문에 유틸리티 함수, 정적 속성인 경우 인스턴스 간에 복제할 필요가 없는 데이터를 만들 때 사용되곤 한다.

클래스 개념은 익숙해서 이해하는게 어렵지는 않았는데... 뒤에서 만날 클로저 개념이 잘 와닿지 않았다. 글로 정리를 해봐야 머릿 속에서 정리될 것 같다. 🤯

profile
느리더라도 조금씩, 꾸준히

0개의 댓글