객체 지향 프로그래밍은 데이터와 기능을 별개로 관리하지 않고 한번에 묶어서 처리한다. 자바스크립트는 엄밀히 객체 지향 프로그래밍 언어는 아니지만, 객체 지향적으로 코드를 짤 수 있다.
객체를 만들 때, ES5까지는 생성자 함수를 사용하여 객체 지향 프로그래밍을 구현했다. 그렇지만 ES6에 들어서 class를 사용하여 객체를 생성할 수 있다. 보다 간편하고 직관적으로 생성할 수 있다. (상속이 가능하다.)
이 때 만들어진 객체를 인스턴스라고 한다.
객체를 생성할 수 있는 청사진 또는 템플릿
ES5의 생성자 함수와 ES6의 class 키워드를 비교해보자.
*ES5* 생성자함수
function Car (brand, name, color) {
this.brand = brand ;
this.name = name ;
this.color = color ;
}
Car.prototype.drive = function() {
console.log (this.name + '가 운전을 시작합니다');
}
*ES6* class
class Car {
constructor (brand, name, color) { // 생성자 함수 constructor
this.brand = brand ; // 중괄호 안 코드 : 인스턴스를 만들 때 실행되는 코드
this.name = name ;
this.color = color ;
}
drive() {
console.log (this.name + '가 운전을 시작합니다');
}
}
어떠한 클래스를 바탕으로 만들어진 객체
class Car {
constructor (brand, name, color) {
this.brand = brand ;
this.name = name ;
this.color = color ;
}
drive() {
console.log(this.name + "가 운전을 시작합니다");
}
}
//인스턴스 생성
const avante = new Car ('hyundai', 'avante', 'black') ;
console.log(avante);// Car { brand: 'hyundai', name: 'avante', color: 'black' }
avante.drive(); // avante가 운전을 시작합니다
클래스의 정적 프로퍼티와 메소드를 정의할 때 static 키워드를 이용한다.
class Car {
static carHorn = "bbang"; // 정적 프로퍼티
constructor(brand, name, color) {
this.brand = brand;
this.name = name;
this.color = color;
}
static makeCar = () => { // 정적 메소드
return new Car ('kia', 'k5', 'white')
}
drive() {/Users/mjwoong/Desktop/드림코딩/직접 필기/6. 클래스/1.클래스기본.js
console.log(this.name + "가 운전을 시작합니다");
}
}
console.log(Car.carHorn); // bbang // 클래스를 이용하여 정적 프로퍼티 호출
const k5 = Car.makeCar() // 클래스를 이용하여 정적 메소드 호출
console.log(k5); // Car { brand: 'kia', name: 'k5', color: 'white' }
클래스에 있는 필드와 메소드는 기본적으로 외부에서 접근이 가능하다. => public 필드 및 메소드
접근제어자를 이용하면 필드와 메소드를 캡슐화하여 외부에서의 접근을 막을 수 있다. => private 필드 및 메소드
class Car {
constructor(brand, name, color) {
this.brand = brand;
this.name = name;
this.color = color;
}
drive = () => {
console.log(this.name + "가 운전을 시작합니다");
}
}
const k5 = new Car ('kia', 'k5', 'white')
console.log(k5);
// Car { drive: [Function: drive], brand: 'kia', name: 'k5', color: 'white' }
접근제어자를 이용하여 위에 출력된 인스턴스에서 color 필드와 drive 메소드를 외부에서 접근이 불가능하게 해보자.
class Car {
#color; // 클래스 바디에 #color
constructor(brand, name, color) {
this.brand = brand;
this.name = name;
this.#color = color; // 사용하는 곳에도 #을 붙여줌.
}
#drive = () => {
console.log(this.name + "가 운전을 시작합니다");
}
}
const k5 = new Car ('kia', 'k5', 'white')
console.log(k5); // Car { brand: 'kia', name: 'k5' } => 외부에서 color프로퍼티와 drive 메소드 접근x
---------------------------------------------------------------------------------------------
k5.#color = 'blue' // 외부에서 접근 불가능.
// => SyntaxError: Private field '#color' must be declared in an enclosing class
이처럼, 클래스 내부에서만 접근 및 사용을 하게하려면
해당 필드와 메소드 앞에 #을 붙여 외부에서 접근이 불가능하게 할 수 있다.
다른 클래스의 필드와 메소드를 그대로 물려받는 것을 의미한다.
필드나 메소드가 겹치는 클래스들을 만들려고 할 때 유용하다. 부모 클래스로부터 상속받은 자식 클래스들은 공통된 부분을 같이 공유하고 각자 필요한 점을 추가 구현할 수 있다.
클래스 상속을 이용하면코드를 재사용
하여 중복되는 코드를 최소화 할 수 있다는 장점이 있다.
예시) 부모클래스로 사람을 나타내는 클래스를 만들고 회사원과 학생을 나타내는 클래스 각각를 만들어 상속을 구현해보자.
(3개의 코드는 모두 연속된 코드)
<부모 클래스 Person>
class Person {
constructor (gender, age) {
this.gender = gender;
this.age = age;
}
eat () {
console.log('밥먹자');
}
}
<Person의 자식 클래스 OfficeWorker>
class OfficeWorker extends Person { // extends 키워드로 상속 관계가 정의됨.
work () { // OfficeWorker 만의 메소드 추가
console.log('일하자');
}
}
const officeWorker = new OfficeWorker ('여자', '30');
console.log(officeWorker);// OfficeWorker { gender: '여자', age: '30' }
officeWorker.eat();// 밥먹자
officeWorker.work();// 일하자
<Person의 자식 클래스 Student>
class Student extends Person {
constructor (gender, age, grade) {
super(gender, age); //super 키워드
this.grade = grade;
}
eat () { // 오버라이딩(Overriding)
console.log('급식실가서 밥먹자');
}
study () {
console.log('공부하자');
}
}
const student = new Student ('남자', '18', '2')
console.log(student); // Student { gender: '남자', age: '18', grade: '2' }
student.eat(); // 급식실가서 밥먹자
student.study(); // 공부하자
OfficeWorker와 Student 클래스는 Person 클래스에게서 필드와 메소드를 그대로 상속받았다. 그 이후 각자 필요한 것을 구현했음을 알 수 있다.
부모 클래스에서 상속받은 constructor에 추가할 것이 없다면 constructor 함수를 생략하면 된다.(OfficeWorker 참고)
그에 비해 부모 클래스에서 상속받은 constructor에 추가를 하려면 super키워드로 부모클래스의 constructor를 호출한 후에 추가하여 구현할 수 있다. (Student 클래스 참고)
extends
키워드로 부모 클래스에서 자식 클래스로의 상속이 이루어진다. 필드와 메소드를 그대로 물려받는다.
super
키워드는 부모 클래스를 참조하거나 부모 클래스의 constructor를 호출할 때 사용한다.
오버라이딩
부모 클래스에게 상속받은 메소드를 자식 클래스에서 재정의하는 것을 말한다.