개요
Javscript의 객체지향프로그래밍에 대해 알아본다.
Checklist
객체지향 프로그래밍
객체지향 프로그래밍은 무엇일까요?
→ OOP, Object Oriented Programming
→ 프로그램의 동작은 여러 객체들이 모여 이루어진다는 개념에서 출발한다.
→ 객체는 크게 두가지 특징인 속성(attribute)과 행동(Behavior)을 가지고있으며, 특정 속성을 가진 객체들의 행동이 맞물려 프로그램 동작이 이루어진다는 개념이다.
→ ※ python에서 활용하는 객체개념과 동일한 개념이지만, class를 통한 구현(python)과 프로토타입기반의 객체프로그래밍(javscript)을 통한 구현이라는 점에서 다르다.
프로토타입 기반의 객체지향 프로그래밍은 무엇일까요?
→ Python이 class 기반의 객체지향이라면, Javascript는 프로토타입 기반의 객체지향이다.
→ 객체를 재활용할 경우 대여의 개념인 class와는 다르게(객체가 서로 나뉘어져 있음), 항상 기존 객체(원형)을 참조한다는 개념이다.
→ 모든 변수, 함수, component 등은 prototype을 보유하고 있다는 특징을 가지고 있다(단, boolean과 같은 원시형태는 prototype이 존재하지 않는다).
자바스크립트의 클래스는 이전의 프로토타입 기반의 객체지향 구현과 어떤 관계를 가지고 있나요?
→ class가 없던 Javascript는 객체를 생성할 때 별도의 내부 생성자없이 바로 객체를 생성하였고, 이에 따른 속성이나 행동 값들을 부여해주었다.
→ ES6이후 생긴 class에서는 constructor 생성자를 통해 정의해줄 수 있고, 외부 생성자인 new를 통해 class를 생성하거나 상속받을 수 있다.
javascript object
※ object를 통해 prototype이 정의됨
function Animal(type, name, sound) {
this.type = type;
this.name = name;
this.sound = sound;
}
prototype
function Animal(type, name, sound) {
this.type = type;
this.name = name;
this.sound = sound;
}
Animal.prototype.say = function() {
console.log(this.sound);
};
javascript class
class Animal {
constructor(type, name, sound) {
this.type = type;
this.name = name;
this.sound = sound;
}
※ OOP의 3대 요소 : 캡슐화/다형성/상속
캡슐화(encapsulation), 정보은닉(informaton hiding)
→ private 속성을 바탕으로 객체간 정보공유를 통해 발생하는 버그나 데이터 임의변경, 의존성 등을 개선하기위해 고안된 개념이다.
→ 캡슐화 : 데이터 속성과 행동을 하나의 함수(prototype)에서 정의하며, 외부에서의 접근을 허용하지 않는 특성이다.
→ 정보은닉 : 캡슐화에서 확장되는 개념으로, 한 객체의 정보가 다른 객체와의 정보공유를 허용하지 않는 특성이다.
다형성이란 무엇인가요? 다형성은 어떻게 코드 구조의 정리를 도와주나요?
→ 하나의 클래스가 다양한 형태와 동작방식을 가질 수 있다는 개념으로, 동일한 prototype임에도 실행결과가 다른 다양한 객체로써 활용할 수 있다는 의미이다.
→ 주로 상속을 통해 클래스를 확장해가는 것으로 이해하면 되며, 클래스의 속성이나 동작방식을 넓혀가는 것을 의미한다.
상속이란 무엇인가요?
→ 쉽게 말하면 class 확장, 모든 class는 다른 class의 속성과 행동을 유지한채 종속적인 관계의 class를 생성할 수 있다.
→ ※ 기본적으로 class나 prototype은 최상위 class인 부모 class와, 이를 확장하여 부모 class의 속성과 행동을 동일하게 사용할 수 있는 자식 class로 구분할 수 있다.
→ 상속의 핵심개념 : 추상화(abstraction), 속성 및 행동의 중복 제거
객체지향 프로그래밍과 코드 재활용
상속의 한계
→ 객체는 기본적으로 독립적이어야 하며, application은 이러한 독립적인 객체들의 기능이 긴밀하게 모여 이루어진 문서이자 집합체이다.
→ 상속은 보통 기존의 class에서 속성과 기능을 추가할때 활용되는 개념으로, 추가기능이 많아진다면 코드 나 용량 측면에서 과부하가 이루어진다(클래스 폭발).
→ 이와 같이 부모 class(prototype)의 속성과 행동을 그대로 유지하여 확장받는 상속의 특성상, 이러한 객체지향 프로그래밍의 기조를 유지하기는 매우 힘들다.
OOP의 합성(Composition)이란 무엇인가요?
→ 이러한 상속의 단점을 보완하면서 코드 재사용을 가능하도록 해주는 기능이 합성(Composition)이다.
→ 상속의 경우 부모 class에 대한 외부 생성자를 생성한 후 별도의 접근이 필요하지만, 합성을 할 경우엔 부모/자식 class 상관없이 한 줄의 코드로 직접적인 접근이 가능해진다.
Inheritance
Card card = new Card;
value = card.NormalPolicy();
Composition
Card card = new Card(new VaxPolicy(0.1, new NormalPolicy());
합성이 상속에 비해 가지는 장점은 무엇일까요?
→ 상속의 경우 컴파일 단계에서 관계가 고정되어 런타임 시점에서 class간 속성 및 관계를 변화시킬 수 없다.
→ 합성은 이러한 단점을 보완하여, 런타임 시점에서 class 관계를 변화시킬 수 있다.
protected property(private 속성의 전신)
→ 마치 보호커버와 같이, application의 세부내용들을 보호할 목적으로 객체로의 접근을 제한하는 것을 의미한다.
→ 내부인터페이스라고도 하며, 특정 인터페이스를(protected 속성을 생성한 프로토타입) 통해서만 접근할 수 있다.
→ ※ python class에서는 private 속성을 통해 구현하며, javascript에서는 protected 속성을 통해 구현한다.
참조개념
python "객체지향언어"와의 비교
→ 결론적으로는 python의 객체와 javascript의 객체는 서로 동일한 개념이다.
→ python에서 선언하는 문자들은 모두 객체이기 때문에, 모든 문자들은 고유의 속성과 행동을 가진다.
→ 다만 python에서는 객체속성을 property(프로퍼티), 객체행동을 method(메소드)라 부른다(※ Javascript에서의 객체속성은 state(상태), 객체행동은 behavior(행동).)
다만, python은 class기반의 언어이다.
→ python에서 객체를 생성하는 방법은 class라는 틀을 통해 이루어지며, 하나의 class 내부에서 모든 property와 method를 정할 수 있다.
Javascript는 class 기반의 언어는 아니다.
→ 기존의 Javascript는 Prototype 기반의 프로그래밍으로, class가 존재하지 않았다.
→ python class와 javascript에서의 객체지향언어의 상속(Inheritance), 캡슐화(정보은닉) 등의 형태는 다르기 떄문에, 각 언어에 맞는 pattern 학습이 필요하다.
→ 최근 ES6 도입 이후에서야 javscript에서의 class 생성이 가능해졌다.
프라이빗필드(#)
→ 최근 Javascript에 추가된 protected 속성을 강화한 프라이빗 필드이다.
→ protected 속성이 생성자(let prototype = new prototype)을 통해서도 접근이 가능하다면, private은 생성자를 통해서 접근이 불가능하다.
반드시 프라이빗 필드를 정의한 prototype 내부에서, 객체로 접근하기위한 내부생성자(set)를 선언해줘야 접근이 가능하다.
javascript의 private 속성 예시
class SuperMarket {
#product = 200;
#CheckValue(value) {
if (value < 0) throw new Error("물건가격을 다시 확인해주세요.");
if (value > this.#producet) throw new Error("적정가격을 초과하였습니다.");
}
}
let Market1 = new SuperMarket();
// 클래스 외부에서 private에 접근할 수 없음
Market1.#checkValue(150); // Error(*접근불가)
Market1.#product = 1000; // Error(*접근/수정불가)
class SuperMarket {
#product = 200;
//private 속성에 접근하기 위해선 별도의 내부 get/set 생성자 선언이 필요하다.
get yourPrice() {
return this.#waterAmount;
}
//private 속성에 접근하기 위해선 별도의 내부 get/set 생성자 선언이 필요하다.
set yourPrice(value) {
if (value < 0) throw new Error("가격은 0이하가 될 수 없습니다.");
this.#waterAmount = value;
}
}
let Market1 = new SuperMarket();
Market1.yourPrice() = 200;
alert(machine.#waterAmount); // Error (*접근불가)
정리
javascript / python
https://velog.io/@suasue/JavaScript-%EA%B0%9D%EC%B2%B4-%ED%8C%8C%EC%9D%B4%EC%8D%AC%EA%B3%BC-%EB%B9%84%EA%B5%90%ED%95%98%EB%A9%B0-%EB%B0%B0%EC%9A%B0%EA%B8%B0
Javascript protected / private
https://ko.javascript.info/private-protected-properties-methods
OOP의 3대요소
https://hyperline.tistory.com/11
캡슐화 / 정보은닉
https://photojin.tistory.com/93
다형성 / 상속
https://codevang.tistory.com/81
프로토타입(prototype)
https://poiemaweb.com/js-prototype
객체/프로토타입/class
https://learnjs.vlpt.us/basics/10-prototype-class.html