객체 지향 프로그래밍과 클래스
객체 지향 프로그래밍은 하나의 모델이 되는 청사진(blueprint)을 만들고,
그 청사진을 바탕으로 한 객체(object)를 만드는 프로그래밍 패턴이다.
→ 청사진을 클래스(class)
→ 청사진을 바탕으로 한 객체를 인스턴스 객체(instance object) 라고 부른다.
📌 클래스는 객체 지향 프로그래밍에서 특정 객체를 생성하기 위해 변수와 메서드를 정의하는 일종의 틀로, 객체를 정의하기 위한 상태(멤버 변수)와 메서드(함수)로 구성된다.
📌 자바스크립트에서 클래스는 함수의 한 종류로 기존 prototype 기반 패턴의 syntactic sugar(기존 문법을 쉽게 읽을 수 있게 만든 문법)이다.
💬 클래스는 ES6에서 추가된 문법으로, ES6 이전에는 클래스를 어떤 방식으로 구현했는지 먼저 알아보고, 클래스의 기본 문법과 클래스 상속에 대해 알아보자.
👩🏻💻 ES5와 ES6의 프로토타입으로 클래스 구현 예시
example 1. 간단 예시 (create Car)
/* ES5: 함수로 클래스를 정의 */
function Car(brand, name, color) { // 생성자 함수
this.brand = brand;
this.name = name;
this.color = color;
}
// 메서드 정의
Car.prototype.refuel = function() { ... }
Car.prototype.drive = function() { ... }
/* ES5: 함수로 클래스를 정의 */
function Car(brand, name, color) { // 생성자 함수
this.brand = brand;
this.name = name;
this.color = color;
}
// 메서드 정의
Car.prototype.refuel = function() { ... }
Car.prototype.drive = function() { ... }
example 2. 좀 더 복잡한 예시 + 상속 (make Cocktatil)
/* ES5: 함수로 클래스를 정의 */
function Cocktail(name, base, method) { // 생성자 함수
this.name = name;
this.base = base;
this.method = method;
}
// 메서드 정의
Cocktail.prototype.make = function() { console.log( `${this.method} 하는 중...` ) }
Cocktail.prototype.serve = function() { console.log( `${this.name} 서빙중...` ) }
// 상속
function Highball(name, base, method, softDrink) {
Cocktail.call(this, name, base, method);
this.softDrink = softDrink;
}
Highball.prototype = Object.create(Cocktail.prototype);
Highball.prototype.constructor = Highball;
Highball.prototype.putIce = function(num) {
console.log( `얼음 ${num}개 넣는 중...` );
}
const cosmopolitan = new Cocktail("cosmopolitan", "vodka", "shake");
const whiskyHighball = new Highball("whiskyHighball", "whisky", "build", "soda");
console.log( cosmopolitan ); // Cocktail { name: 'cosmopolitan', base: 'vodka', method: 'shake' }
console.log( cosmopolitan.make() ); // shake 하는 중...
console.log( cosmopolitan.serve() ); // cosmopolitan 서빙중...
console.log( cosmopolitan.putIce() ); // TypeError: cosmopolitan.putIce is not a function
console.log( whiskyHighball ); // Highball { name: 'whiskyHighball', base: 'whisky', method: 'build', softDrink: 'soda' }
console.log( whiskyHighball.make() ); // build 하는 중...
console.log( whiskyHighball.serve() ); // whiskyHighball 서빙중...
console.log( whiskyHighball.putIce(10) ); // 얼음 10개 넣는 중...
/* ES6: class 키워드로 정의 */
class Cocktail {
constructor(name, base, method) { // 생성자 함수
this.name = name;
this.base = base;
this.method = method;
}
// 메서드 정의
make() { console.log( `${this.method} 하는 중...` ) }
serve() { console.log( `${this.name} 서빙중...` ) }
}
// 상속
class Highball extends Cocktail {
constructor(name, base, method, softDrink) {
super(name, base, method);
this.softDrink = softDrink;
}
putIce(num) { console.log( `얼음 ${num}개 넣는 중...` ) }
}
const cosmopolitan = new Cocktail("cosmopolitan", "vodka", "shake");
const whiskyHighball = new Highball("whiskyHighball", "whisky", "build", "soda");
console.log( cosmopolitan ); // Cocktail { name: 'cosmopolitan', base: 'vodka', method: 'shake' }
console.log( cosmopolitan.make() ); // shake 하는 중...
console.log( cosmopolitan.serve() ); // cosmopolitan 서빙중...
console.log( cosmopolitan.putIce() ); // TypeError: cosmopolitan.putIce is not a function
console.log( whiskyHighball ); // Highball { name: 'whiskyHighball', base: 'whisky', method: 'build', softDrink: 'soda' }
console.log( whiskyHighball.make() ); // build 하는 중...
console.log( whiskyHighball.serve() ); // whiskyHighball 서빙중...
console.log( whiskyHighball.putIce(10) ); // 얼음 10개 넣는 중...
👾 클래스(class)란?
⬇︎ 클래스 기본 문법
// 클래스 생성
class MyClass {
constructor() {...}
method1() {...}
method2() {...}
...
}
// 클래스를 통한 인스턴스 객체 생성
const instance1 = new MyClass();
• 선언식으로 정의한 클래스의 이름은 constructor
와 동일하고, constructor
는 new
연산자 없이 호출할 수 없다.
• 각각의 인스턴스는 클래스의 고유한 속성과 메서드를 가진다.
• 클래스 이름은 명사들의 조합으로 이루어지며 첫 글자는 대문자로 지정하는 것이 관례이다. (PascalCase)
✔️ 생성자 함수 constructor
constructor는 인스턴스가 초기화될 때 실행하는 생성자 함수로 객체의 기본 상태를 설정해주는 생성자 메서드로 인스턴스가 생성될 때 실행되며 new연산자 에 의해 자동으로 호출된다. (return 값을 만들지 않음)
class Student {
constructor(name, grade, language) {
this.name = name,
this.grade = grade,
this.language = language
}
study() {
console.log("공부를 시작합니다.");
}
spaek() {
console.log("발표를 합니다.")
}
}
let Elle = new Student("Elle", 2, "English");
Elle.language // English
Elle.study() // 공부를 시작합니다.
• constructor
는 클래스 내에 한 개만 존재할 수 있으며, constructor
의 파라미터에 전달한 값은 클래스 필드에 할당된다.
• constructor
는 생략하면 클래스에 constructor() {}
빈 객체를 생성한다.
→ 인스턴스에 프로퍼티를 추가하려면 인스턴스를 생성한 이후, 프로퍼티를 동적으로 추가해야 한다.
• constructor
는 인스턴스 생성과 동시에 클래스 필드의 생성과 초기화를 실행하기 때문에 클래스 필드를 초기화해야 한다면 constructor
를 생략해서는 안된다.
• constructor
는 부모 클래스의 constructor
를 호출하기 위해 super
키워드를 사용할 수 있다.
• constructor
내부에서 선언한 클래스 필드는 클래스가 생성할 인스턴스를 가리키는 this
에 바인딩한다
→ 클래스 필드는 클래스가 생성할 인스턴스를 프로퍼티가 되며, 클래스의 인스턴스를 통해 클래스 외부에서 언제나 참조 할 수 있다. (언제나 public)
✔️ 클래스 필드(class field)
클래스 필드란 클래스 내부의 캡슐화된 변수를 말한다. 데이터 멤버 또는 멤버 변수라고도 부른다. 클래스 필드는 인스턴스의 프로퍼티 또는 정적 프로퍼티가 될 수 있다. 쉽게 말해, 자바스크립트의 생성자 함수에서 this에 추가한 프로퍼티를 클래스 기반 객체지향 언어에서는 클래스 필드라고 부른다.
• 클래스 필드(class field)를 사용하면 어떤 종류의 프로퍼티도 클래스에 추가할 수 있다.
class Person {
name = "Jane";
age = prompt("How old?", "20");
sayHi() { console.log(`Hi, ${this.name}`) }
}
// new Person().sayHi(); // Hi, Jane
const person = new Person();
person.sayHi() // Hi, Jane
console.log(person.name) // Jane
console.log(person.age) // 20
// name과 age는 Person.prototype이 아닌 개별 객체에 클래스 필드가 설정된다.
console.log(Person.prototype.name) // undefined
console.log(Person.prototype.age) // undefined
→ 프로퍼티이름 = “값”
으로 클래스 필드를 만들 수 있다.
→ 클래스 필드에 설정된 값은 class의 prototype이 아닌 개별 객체에 설정된다.
→ 클래스 필드에 복잡한 표현식이나 함수 호출 결과를 사용할 수도 있다.
👾 클래스 상속
클래스 상속이란 어떤 클래스의 기능을 다른 클래스에 상속시킨 후 추가적인 기능을 명시하여 원래의 기능을 확장하는 방법이다.
✔️ extends 키워드
class를 정의할 때 클래스 이름 뒤에 extends 키워드를 명시하고 상속받고자 하는 부모 클래스의 이름을 지정한다.
// extends는 부모 클래스(base class)를 상속받는 자식 클래스(sub class)를 정의할 때 사용
class Child extends Parent
/* 기본 기능을 갖는 클래스 */
class sayHello {
eng() { console.log("Hello Javascript") }
}
/* 기본 기능을 확장하는 클래스 */
// 부모의 기능을 상속받고, 추가로 자신이 구현하는 기능도 사용할 수 있다.
class sayHelloWorld extends sayHello {
kor() { console.log("안녕하세요. 자바스크립트") }
}
const say = new sayHelloWorld();
say.eng(); // Hello Javascript
say.kor(); // 안녕하세요. 자바스크립트
👩🏻💻 example
// 부모 클래스
class Animal {
constructor(name) {
this.speed = 0;
this.name = name;
}
run(speed) {
this.speed = speed;
console.log(`${this.name} 은/는 속도 ${this.speed}로 달립니다.`);
}
stop() {
this.speed = 0;
console.log(`${this.name} 이/가 멈췄습니다.`);
}
}
let animal = new Animal("동물");
// 자식 클래스
class Rabbit extends Animal {
hide() {
console.log(`${this.name} 이/가 숨었습니다!`);
}
}
let rabbit = new Rabbit("흰 토끼");
rabbit.run(5); // 흰 토끼 은/는 속도 5로 달립니다.
rabbit.hide(); // 흰 토끼 이/가 숨었습니다!
👩🏻💻 example extends
뒤에 표현식이 올 수도 있다.
function f(phrase) {
return class {
sayHi() { alert(phrase) }
}
}
// class User는 f("Hello")의 반환값을 상속받는다.
class User extends f("Hello") {}
new User().sayHi(); // Hello
→ 이 방법은 조건에 따라 다른 클래스를 상속받고 싶을 때 유용하다. 조건에 따라 다른 클래스를 반환하는 함수를 만들고, 함수 호출 결과를 상속받게 하면 된다.
✨ 참고로, 리액트에서 컴포넌트를 사용하는 방법이 이와 같다.
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>
}
}
✔️ super 키워드
super
키워드는 부모 클래스를 참조(Reference)할 때 또는 부모 클래스의 constructor를 호출할 때 사용한다.
class Human {
constructor(name, age, location) {
this.name = name;
this.age = age;
this.location = location;
}
eat(food) { console.log(`${this.name}이 ${food}을(를) 먹습니다.`) }
sleep() { console.log(`${this.name}이 잠을 잡니다.`) }
live() {
console.log(`거주지: ${this.location}`)
return `${this.location}`;
}
}
class Student extends Human {
constructor(name, age, location, major) {
super(name, age, location); // ①
this.major = major;
}
study() { console.log(`${this.major} 공부중...`) }
goToSchool() { console.log(`${super.live()} 에서 학교로 갑니다.`) } // ②
}
const student = new Student("Amy", 20, "Seoul", "English");
① super
메소드는 부모 클래스의 constructor를 호출하면서 인수를 전달한다. 자식 클래스의 constructor에서 super()
를 호출하지 않으면 this에 대한 참조 에러가 발생한다.
→ 자식 클래스의 생성자에선 this를 사용하기 전에 반드시 super
를 호출해야 한다.
② super
키워드는 부모 클래스의 필드 또는 메소드를 참조한다.
✔️ 메서드 오버라이드 (override)
부모 클래스가 가지고 있는 메서드를 자식 클래스가 재정의하여 사용하는 방식으로 자식 클래스가 정의한 메서드에 의해 부모 클래스의 메서드는 가려지게 된다.
자료출처: poiemaweb, JAVASCRIPT.INFO
✏️ 공부하며 정리한 내용입니다. 잘못된 정보나 더 공유할 내용이 있으면 댓글로 알려주세요!
읽어주셔서 감사합니다 😊
'Frontend Dev > JavaScript' 카테고리의 다른 글
ES6, 비동기 처리를 위한 프로미스 (Promise) (0) | 2023.05.17 |
---|---|
자바스크립트의 프로토타입 (prototype) (0) | 2023.05.15 |
자바스크립트와 객체 지향 프로그래밍 (Object Oriented Programming) (0) | 2023.05.13 |
디폴트 매개변수와 나머지 매개변수 (with arguments 객체) (0) | 2023.05.07 |
함수의 매개변수(parameter)와 인수(argument 전달인자) (0) | 2023.05.07 |