말로만 듣던 객체지향! 그것은 바로
class
로 잘 나눠서 하는 개발이라는 뜻이었다.
class
라고 한다.class
에는 fields
와 methods
가 종합적으로 구성되어 있다.캡슐화
라고 한다.이 모든 것들이 일어나는 것이 바로 객체지향 언어
class
는 '템플릿'이다. class
에 데이터를 넣은 것이 바로 object
class Person {
// constructor
constructor(name, age) {
// fields
this.name = name;
this.age = age;
}
// methods
speak () {
console.log(`${this.name}: hello!`);
}
} // Person이라는 class는 name, age라는 fields와 speak라는 method로 이루어져 있다.
this
는 '생성된 오브젝트' 라는 의미이다.
const ellie = new Person('ellie', 20); // 새로운 object를 만들 때 new라는 키워드를 쓴다.
console.log(ellie.name); // ellie
console.log(ellie.age); // 20
ellie.speak(); // 함수도 호출 가능. ellie: hello! 라고 출력됨
get
을 이용해 값을 return
, set
을 이용해 값을 설정할 수 있다.set
은 값을 설정하기 때문에 value
를 받아와야 한다.class
를 만들어보자.class User {
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
get age() {
return this._age;
}
set age(value) {
this._age = value < 0 ? 0 : value; // value가 음수면 0으로 쓰고 아니면 value 그대로 쓸래!
// 혹은 아래와 같이 경고를 날려도 된다.
// if (value < 0) {
// throw Error('age can not be negative');
// }
}
}
const user1 = new User('Steve', 'Jobs', -1);
console.log(user1.age); // 0 이라고 나온다.
_
을 붙인다. (2, private 이런거 붙여도 되긴 함)User
라는 class
에는 firstName
, lastName
, _age
3개의 fields가 있는 것이다..age
라고 할당하고 호출할 수 있는 것은 내부적으로 getter와 setter를 이용하기 때문이다. (??? 몬말몰)get
, set
바로 다음에 쓰는 age
는 뭐지..? 그냥 함수 이름인가..?age
가 맞다._
로 시작하는 프로퍼티는 객체 내부에서만 활용하고, 외부에서는 건드리지 않는 것이 관습이다.#
을 붙이면 된다.class
내부에서만 보이고, 접근/변경이 가능하다.class
자체에 추가되므로 class.method
이런 식으로 써야한다. (object.method
(X))class Article {
static publisher = 'Dream Coding';
constructor(articleNumber) {
this.articleNumber = articleNumber;
}
static printPublisher() {
console.log(Article.publisher);
}
}
// 오브젝트 생성
const article1 = new Article(1);
const article2 = new Article(2);
console.log(article1.publisher); // undefined
console.log(Article.publisher); // Dream Coding
Article.printPublisher(); // Dream Coding
사각형, 삼각형, 원을 class
로 정의하려고 한다. 세 가지 클래스는 공통적으로 높이, 넓이 값을 가지는 '도형'이다. 그래서! 반복되는 속성들을 그 때마다 계속 적는 것이 아니라, 도형(shape)을 한 번에 빡 정의한 다음에 공통적으로 쓰이는 속성 값을 재사용한다. 타이핑 할 것도 줄고 유지 보수 하기에도 좋다.
class Shape {
constructor(width, height, color) {
this.width = width;
this.height = height;
this.color = color;
}
draw() {
console.log(`drawing ${this.color} color of`);
}
getArea() {
return this.width * this.height;
}
}
Shape
이라는 class
를 정의하였다. 이 상태에서 Rectangle
이라는 class
를 만들고 싶다면 반복해서 또 쓰는 것이 아니라 extends
라는 키워드를 사용해서 Shape
를 연장해서 사용하면 된다.
class Rectangle extends Shape {}
까지만 써도 Shape의 모든 fields와 methods가 자동으로 포함된다.
class Rectangle extends Shape {}
class Triangle extends Shape {}
const rectangle = new Rectangle(20, 20, 'blue');
const triangle = new Triangle(20, 20, 'red');
그런데, 삼각형의 면적을 구하기 위해 console.log(triangle.getArea());
를 쓰면, 400이 출력되는데 이것은 틀린 값이다. 여기서 우리가 필요한 함수만 재정의해서 사용할 수 있다.
class Triangle extends Shape {
getArea() {
return (this.width * this.height) / 2;
}
}
console.log(triangle.getArea()); // 200
draw()
도 마찬가지로 재정의할 수 있는데, 재정의하면 공통적으로 정의했던 것은 아예 실행이 안 된다. 만약 공통적으로 정의한 것과 재정의한 것을 함께 쓰고 싶다면 다음과 같이 하면 된다.
class Triangle extends Shape {
draw() {
super.draw(); // 부모의 method 호출. drawing red color 출력됨
console.log('🔺');
}
getArea() {
return (this.width * this.height) / 2;
}
}
(왼쪽) instance of (오른쪽)