
객체 지향 프로그래밍(java, C++, Python 등) vs 절차 지향 프로그래밍(C)
절차 지향 프로그래밍은 프로시저 호출을 통해 처리하는 방식인 반면에
객체 지향 프로그래밍은 데이터와 기능을 한곳에 묶어서 처리하는 방식
javascript의 경우, 컴파일 프로그래밍 언어에 속하기에 객체 지향 프로그램이라고 할 수 없다.
하지만 객체 지향 프로그래밍이 가능하다.
함수와 함수가 선언된 어휘적 환경의 조합
let counter1 = {
value: 0,
increase: function() {
this.value++ // 메서드 호출을 할 경우, this는 counter1을 가리킵니다
},
decrease: function() {
this.value--
},
getValue: function() {
return this.value
}
}
counter1.increase()
counter1.increase()
counter1.increase()
counter1.decrease()
counter1.getValue() // 2
카운터 코드
function makeCounter() {
let value = 0;
return {
increase: function() {
value++;
},
decrease: function() {
value--;
},
getValue: function() {
return value;
}
}
}
let counter1 = makeCounter()
counter1.increase()
counter1.getValue() // 1
let counter2 = makeCounter()
counter2.decrease()
counter2.decrease()
counter2.getValue() // -2
클로저 모듈 패턴으로 구현한 카운터
하나의 모델이 되는 청사진(blueprint)을 만들고, 그 청사진을 바탕으로 한 객체를 만드는 프로그래밍 패턴

하나의 모델이 되는 청사진(blueprint) = class
그 청사진을 바탕으로 한 객체를 만드는 프로그래밍 패턴(object) = instances
ES5에서는 함수 사용
function Car(brand, name, color) {
//인스턴스가 만들어질 때 실행되는 코드
}
ES6에서는 클래스 사용 가능
class Car {
constructor(brand, name, color) {
//인스턴스가 만들어질 때 실행되는 코드
}
}
속성 = brand, name, color
메소드 = 객체에 딸린 함수
this = 인스턴스 객체
객체 지향 프로그래밍 패러다임 == 사람이 세계를 보고 이해하는 방법
Encapsulation(캡슐화)
캡슐화는 코드가 복잡하지 않게 만들고, 재사용성을 높인다.
Inheritance (상속)
부모 클래스의 특징을 자식 클래스가 물려받는 것
물려받으면서 속성과 메소드를 가져온다.
상속 불필요한 코드를 줄여 재사용성을 높입니다.
Abstraction (추상화)
실제로 노출되는 부분은 단순하게 만듦
캡슐화가 코드나 데이터의 은닉에 포커스가 맞춰져있다면, 추상화는 클래스를 사용하는 사람이 필요하지 않은 메서드 등을 노출시키지 않고, 단순한 이름으로 정의하는 것
추상화는 코드가 복잡하지 않게 만들고, 단순화된 사용으로 변화에 대한 영향을 최소화한다.
Polymorphism (다형성)
객체는 똑같은 이름을 가진 메소드라 하더라도, 조금씩 다른 방식으로 구현될 수 있다.
다형성이 없다면 클래스에 종류별로 분기를 시켜서 하나하나 다르게 만들어야 할 것
다형성으로 인해 동일한 메서드에 대해 if/else if와 같은 조건문 대신 객체의 특성에 맞게 달리 작성하는 것이 가능해진다.
Java나 TypeScript라는 프로그래밍 언어는 클래스 내부에서만 쓰이는 속성 및 메서드를 구분시키기 위해 private이라는 키워드를 제공한다.
TypeScript에서 OOP 패턴으로 구현한 클래스 Animal
class Animal {
private name: string;
constructor(theName: string) {
this.name = theName;
}
}
new Animal("Cat").name; // 사용 불가
// Property 'name' is private and only accessible within class 'Animal'.
name이라는 속성이 존재. 그러나 private 키워드가 붙어 있어서, 클래스 내부에서만 사용 가능
JavaScript에서는 은닉화를 돕기 위해서 일반적으로 클로저 모듈 패턴을 사용한다. 클래스/인스턴스 형태로 만들 때에는 ES2019부터 #이라는 키워드가 도입됨
Java나 TypeScript 언어는 언어의 주요 기능으로 interface를 구현해 놓았습니다. 그러나 이러한 부분은 JavaScript에는 존재하지 않는 기능이다.
TypeScript에서 Interface와 class를 따로 정의한 예시
interface ClockInterface {
currentTime: Date;
setTime(d: Date): void;
}
class Clock implements ClockInterface {
currentTime: Date = new Date();
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) {}
}
인터페이스의 이점은, 인터페이스가 일종의 규약처럼 간주되어, 인터페이스를 클래스로 구현하는 사람들이 이에 맞게 작성할 수 있게 돕는다. 이는 클래스를 이용하는 입장에서 노출된 인터페이스를 통해 "이 클래스는 메서드 이름이 의도한 바대로 작동할 것이다"라는 것을 명백히 드러나게 해 준다. 또한 실질적인 구현 방법을 공개하지 않고, 사용법을 노출시키기에도 유리하다.
어떤 클래스가 외부 공개용으로 모듈처럼 작동할 때에, 이러한 인터페이스는 빛을 발한다. 이러한 인터페이스 사용의 대표적인 예가 API(Application Programming Interface)다.
JavaScript는 프로토타입 기반 언어다. 여기서 프로토타입(Prototype)은 원형 객체를 의미한다.
Javascript에서는 객체를 상속하기 위하여 프로토타입이라는 방식을 사용한다.
class Human {
constructor(name, age) {
this.name = name;
this.age = age;
}
sleep() {
console.log(`${this.name}은 잠에 들었습니다`);
}
}
let kimcoding = new Human('김코딩', 30);
// 실습해보세요
Human.prototype.constructor === Human; //true
Human.prototype === kimcoding.__proto__; //true
Human.prototype.sleep === kimcoding.sleep; //true

클래스 Human과 인스턴스 steve, 프로토타입의 관계

배열 arr와 Array, 프로토타입의 관계
OPP의 특성 중 상속을 JavaScript에서 구현할 때에는 프로토타입 체인을 사용한다.
let kimcoding = new Human('김코딩', 30);
// 속성
kimcoding.age;
kimcoding.gender;
// 메서드
kimcoding.eat();
kimcoding.sleep();
클래스 Human의 속성과 메서드 예시클래스 Human의 속성과 메서드 예시
학생은 학생이기 이전에, 사람이다. 따라서 클래스 Student는 Human의 기본적인 메서드를 상속받을 수 있다. 다만, 학생은 일반적인 사람의 특징에 추가적인 특징이 필요하다.
let parkhacker = new Student('박해커', 22);
// 속성
parkhacker.grade;
// 메서드
parkhacker.learn();
클래스 Student의 속성과 메서드 예시
속성과 메서드를 물려주는 클래스를 부모 클래스(여기서는 Human), 속성과 메서드를 물려받는 클래스를 자식 클래스(여기서는 Student), 그리고 이 과정을 상속이라고 한다.
과제-Beesbeesbees
https://github.com/jeongminsang/fe-sprint-beesbeesbees