6. class vs object

jean·2021년 2월 7일
0
  1. class: fields + methods
    fields만 있는 class는 데이터 클래스라고 부른다.

encapsulation: class 안에서, 밖에서 볼 수 있는 것을 나눠둔 것.

class person {
name; //속성(field)
age; //속성(field)
speak(); //행동(method)
}

  1. class 안에는 데이터가 들어 있지 않고, 틀(템플릿)만 정해놓는 것이다. 클래스 안에 데이터가 들어가면 그것은 object가 된다. class는 실제로 메모리에 올라가지 않는다.

  1. object는 instance of a class이며 많이 만들 수 있다. 데이터가 들어있기 때문에 메모리에도 올라간다.

  1. JavaScript class
    - introduced in ES6
    - syntatical sugar over prototype-based inheritance

class: template
object: instance of a class

  1. Class declaration
    class Person {

    constructor(name, age) {
    this.name = name;
    this.age = age;
    }

    speak() {
    console.log(${this.name}: I'm ${this.age} years old!);
    }
    }

  1. Object 생성
    const yuna = new Person('yuna', 20);

  2. 함수 출력 / 호출
    console.log(yuna.name); //함수 값 출력
    console.log(yuna.age); //함수 값 출력
    yuna.speak(); //함수 메소드 호출

  3. getter & setter
    encapsulation

class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}

const user1 = new User('yuna', -1);

사용자의 name과 age를 받는 Person이란 클래스가 있다고 하자.
user1에 대한 나이가 -1인 것을 볼 수 있는데, 나이는 음수일 수 없으므로 함수를 부르는 사용자가 이상한 짓을 하지 못하도록 getter & setter가 필요하다.

값을 불러오기 위한 get(){} 메소드와 값을 설정하기 위한 set(){} 메소드를 class 안에 추가하면 아래와 같은 모습이다.

class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}

get age() {
return this._age;
}

set age(value) {
this._age = value;
}

}

class 안에 getter를 정의하는 순간,
즉 get age()라는 메소드가 생기는 순간,
constructor 안에 있는 this.age는 메모리 안에 있는 this.age라는 값을 읽어오는 게 아니라, this의 메소드 .age()를 호출하게 된다.

똑같이 class 안에 setter를 정의하는 순간,
즉 set age()라는 메소드가 생기는 순간,
constructor 안에 있는 = age는 (= equal sign)
값을 할당할 때,
set age(value) {} 메소드를 호출하게 된다.

setter 안에 this.age = value; 에도 (= equal sign)이 있는데,
이는 메모리에 값을 직접 할당하는 게 아니라
set age(value) {} 메소드를 호출한다.
이게 무한정 반복되니, 이대로 코드를 실행하면
call stack size exceeded라는 에러가 발생하게 된다.

이것을 방지하기 위해 getter와 setter 안에 쓰이는 변수 이름을 _age와 같이 조금 다르게 만든다.

getter & setter를 설정하고 난 뒤에는
이제 class 안에 총 2개의 fields가 생기게 되는데
1. name
2. _age
이다.

이제 setter 안에서 받아온 value가 음수이면 에러메세지를 출력할 수 있다.

field에는 기호가 들어간 _age가 있지만,
우리가 .age라고 호출할 수 있는 것은
그리고 .age에 값을 할당할 수 있는 것은
내부적으로 getter와 setter를 이용하기 때문이다.

  1. public & private field (정말 최근에 추가된 기능, 쓰려면 BABEL을 이용해야 한다.)

field 이름 앞에 #를 붙이면 private field가 된다. 클래스 외부에서는 이 값을 읽거나 변경할 수 없게 된다.

  1. static
    static이라는 키워드를 사용하면,
    field나 method가
    object와 상관 없이 class 자체에 연결되도록 만들 수 있다.

static 키워드를 사용해서 만든
field나 method는
object 이름.field
object 이름.method() 와 같이 호출하는 것이 아니라

클래스 안에 속한 것이기 때문에
class 이름.field
class 이름.method()와 같이 호출해야 한다.

들어오는 데이터에 상관 없이 공통적으로 class에서 쓸 수 있는 field나 method를 만들 때 쓰인다. 이렇게 하면 메모리를 절약할 수 있기 때문!

  1. 상속
    shape이 동일한 여러개의 rectangle이 있다고 하자.
    shape class를 상속하는 rectangle이라는 class를 만들고 싶을 때, extends라는 키워드를 사용하여 아래와 같이 한다.

class Shape {}

class Rectangle extends Shape {}

const rectangle = new Rectangle(20, 20, 'blue');
rectangle.draw(); // Shape의 메소드인 .draw()를 rectangle 안에서도 부를 수 있다. Rectangle은 Shape를 상속했기 때문에! Rectangle은 Shape의 값이나 메소드를 쓸 수 있다.

상속을 이용하면, class끼리 공통된 field나 method를 모두 다시 작성하지 않아도 계속 재사용할 수 있다. 코드 타입을 덜 해도 되는 것이다.

또한 여러 class에서 수정해야 할 것이 있으면, Shape에서만 수정하면 나머지 상속한 모든 class에서도 수정이 되므로 유지보수가 쉬워진다.

  1. 다형성
    상속한 class는 서로 같은 field와 method를 공유한다.
    하지만 특정 class에서 다른 기능을 주고 싶다면 어떻게 할까?
    예를 들어 아래와 같이 Rectangle과 Triangle 클래스가 있을 때,
    사각형과 삼각형의 넓이를 구하는 method는 달라져야 한다.

class Shape {}
class Rectangle extends Shape {}
class Triangle extends Shape {}

이 때 overriding을 이용한다.
필요한 함수들만 overriding해서 사용하면 된다.

공통적으로 정의된 method도 호출하면서, overriding된 method도 호출하고 싶다면 super.method()를 사용한다.

class Triangle extends Shape {
draw() {
super.draw(); // 부모(super)의 메소드인 Rectangle의 draw()를 호출한다.
console.log();
}
};

  1. instanceof operator: class checking
    이 오브젝트가 이 클래스를 이용해서 만들어진 아이인지 아닌지 확인하는 것

console.log(rectangle instanceof Rectangle);
console.log(triangle instanceof Shape);
console.log(triangle instanceof Object); // true

*특이한 점!
자바스크립트에서 만든 모든 object는 자바스크립트 자체에 있는 Object를 상속한 것이므로 마지막 줄에서 true가 나온다.
확인을 위해 커맨트나 컨트롤 키를 누른 채로 object를 클릭하면 이가 정의된 부분으로 가서 볼 수 있다.

  1. 자바스크립트의 어떤 object던지, 자바스크립트 자체에 공통적으로 존재하는 메소드를 쓸 수 있다.

ex)
triangle.toString(); // [object object] 출력 (쓸모 없는 데이터)

  1. 따라서 각 클래스에서 자바스크립트에 이미 존재하는 메소드를 overriding하여 쓸모 없는 데이터를 의미 있는 데이터로 바꿔 출력할 수도 있다.

class Triangle extends Shape {
toString() {
return 'Triangle: ${this.color}'; // Triangle: blue
}
}

  1. 자바스크립트 object들
    MDN JavaScript reference 참고: 자바스크립트 안에 내장된 object들이 뭐가 있는지 확인할 수 있다.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference

  1. 더하기, 곱하기 등 연산을 수행해주는 함수 만들기

정해진 데이터를 처리하는 경우에는 if문보다는 switch문이 좋다.

0개의 댓글