드디어 올것이 왔다...! 처음 배울 때 아주 어려웠던 객체지향프로그래밍(OOP)을 사용하는 미션이 시작되었다!! JAVA를 많이 다루면서 어렴풋이 이해하고 사용하고 있지만, 확실하게 이해하고 정리하고 사용하는 것보다 더 중요한 것은 없다는 것을 계속해서 느끼고 있다. 이 글에서는 언어종류를 벗어나 개념을 확실하게 공부하고 나만의 언어로 다시 정리하고자 한다.
나는 JavaScript보다 JAVA에 더 익숙하기 때문에, 객체지향을 적극적으로 사용하는게 더 편하다고 느끼고 있었다. 하지만, 오히려 너무 자유로운? JavaScript에서 객체를 어떻게 구성하고 제약사항을 설정해서 객체를 관리해 주는지에 대해서 많은 의문점을 가지고 있었다. 우선, JavaScript든 JAVA든 객체지향이라는 개념은 다르지 않다고 생각하고 개념에 대해서 먼저 정리하고 찬찬히 적용하면서 익혀보고자 한다.
클래스, 객체, 인스턴스의 개념
클래스 : 붕어빵 틀
객체 : 붕어빵 (붕어빵 틀 클래스로 만든 모든 붕어빵)
인스턴스 : 굽기, 팥의 양에 따라서 다 다른 종류의 붕어빵
👉 팥붕어빵, 슈크림붕어빵 은 다른맛의 '음식'이지만, 같은 '붕어빵틀'로 만든 '붕어빵'이라는 종류에 포함된다.
클래스(Class)
- 객체를 만들어 내기 위한 설계도
- 연관되어 있는 변수와 메서드의 집합
객체
- 소프트웨어 세계에서 구현할 대상
- 클래스에 선언되어 있는 모습 그대로 생성된 실체
👉 클래스의 인스턴스
- 모든 인스턴스를 대표하는 포괄적인 의미를 가진다
- oop 관점에서 클래스 타입으로 선언되었을 때 ‘객체’라고 부른다.
인스턴스
- 소프트웨어 세계에 구현된 구체적인 실체
- 즉, 객체를 소프트웨어에 실체화 하면 그것을 ‘인스턴스’라고 부른다.
- 실체화된 인스턴스는 메모리에 할당된다.
- 인스턴스는 객체에 포함된다.
- oop 관점으로 객체가 메로리에 할당되어서, 실제로 사용 될 때, ‘인스턴스’라고 부른다.
- 추상적인 개념과 구체적인 객체 사이의 관계에 초점을 맞춰어서 사용한다.
- 원본(추상적인 개념)으로부터 생성된 복제본
클래스, 객체, 인스턴스의 차이
클래스(Class) VS 객체(Object)
클래스는 ‘설계도’, 객체는 ‘설계도로 구현한 모든 대상’을 의미한다.
객체(Object) VS 인스턴스(Instance)
- 클래스의 타입으로 선언되었을 때 객체라고 부르고, 그 객체가 메모리에 할당되어 실제 사용될 때 인스턴스라고 부른다.
- 객체는 현실 세계에 가깝고, 인스턴스는 소프트웨어 세계에 가깝다.
- 객체는 ‘실체’, 인스턴스는 ‘관계’에 초점을 맞춘다.
- 객체를 ‘클래스의 인스턴스’라고도 부른다.
방금 인스턴스화하여 레퍼런스를 할당한’ 객체를 인스턴스라고 말하지만, 이는 원본(추상적인 개념)으로부터 생성되었다는 것에 의미를 부여하는 것일 뿐 엄격하게 객체와 인스턴스를 나누긴 어렵다.
추상화 기법
- 분류 (Classificatino)
- 객체 → 클래스
- 실재하는 객체들의 공통적인 속성을 공유하는 범부, 추상적인 개념으로 묶는 것
- 인스턴스화(Instantiation)
- 클래스 → 인스턴스
- 범주나 개념으로부터 실재하는 객체를 만드는 과정
- 구체적으로 클래스 내의 객체에 대해 특정한 변형을 정의하고, 이름을 붙인 다음, 그것을 물리적은 어떤 장소에 위치시키는 등의 작업을 통해서 인스턴스를 만드는 것
- 예시(Excemplificaion) 이라고도 부른다.
추가 용어
- 프로퍼티(property)
- 객체 내부의 속성
- 객체 내에 정의 되어 있는 변수(값)
- 메소드(method)
- 객체 안에 프로퍼티로 정의되어 있는 함수
- 캡슐화(encapsulation)
- 객체안의 프로퍼티와, 처리하는 메서드를 하나로 묶어서 외부에 감추어서 보여주지 않는것
- 메소드를 통해서만 프로퍼티에 접근 가능하게 한다.
- 객체내의 정보손상과 오용을 방지하면서 독립성과 이식성이 좋아 객체를 모듈화해서 재사용성을 높인다.
- 객체안의 프로퍼티와, 처리하는 메서드를 하나로 묶어서 외부에 감추어서 보여주지 않는것
- 상속(inheritance)
- 상위 클래스를 말 그대로 상속 받아서 상위 클래스의 멤버들을 공유하는 것
- 상위 클래스에서 설정한 프로퍼티, 메소드를 사용할 수 있다.
- 다형성(polymorphism)
- 프로그램 언어의 각 요소들이 다양한 자료형에 속하게 허가하는 성질을 말한다.
- 기능을 확장하거나, 객체를 타입 변경없이 주입을 통해서 간단하게 다양한 객체를 사용할 수 있게 해준다.
https://developer.mozilla.org/ko/docs/Learn/JavaScript/Objects/Object-oriented_programming
객체 지향 프로그래밍 - Web 개발 학습하기 | MDN
객체 지향 프로그래밍(OOP)은 Java 및 C++를 비롯한 많은 프로그래밍 언어의 기본이 되는 프로그래밍 패러다임입니다. 이 기사에서는 OOP의 기본 개념에 대한 개요를 제공합니다. 클래스와 인스턴스
developer.mozilla.org
JavaScript에서의 클래스
- 화면에 보이는 UI요소, 어떠한 제어를 하는 비UI요소등, 모든 것을 모듈로 만들어서 개발할 수 있다.
- 모듈은 객체(class형태)를 의미한다.
- JavaScript에서 객체의 표현방식은 다양하다.
1. object literal
- class 없이 바로 object로 표현 한다.
- new Object() 없이 바로 인스턴스를 생성한다.
const healthObj = {
name : "달리기",
lastTime : "PM10:12",
showHealth() {
console.log(this.name + "님, 오늘은 " + this.lastTime + "에 운동을 하셨네요");
}
}
healthObj.showHealth();
2. ES Classes pattern - ES2015
- class를 new키워드로 호출하면 constructor가 자동호출된다.
- constructor는 instance를 만들어서 반환한다.
- 객체(instance) 를 만들어서 반환한다.
- ES Classes역시 prototype을 내부적으로 사용한다.
const Health = class {
constructor(name, healthTime) {
this.name = name;
this.healthTime = healthTime;
}
showHealth(){
console.log(this.name + "님, 오늘은 " + this.healthTime + "에 운동을 하셨네요");
}
}
const ho = new Health("crong", "12:12");
ho.showHealth();
3. constructor pattern
- function을 new 키워드로 호출하면, 그 함수는 constructor가 된다.
const Health = function(name,healthTime) {
this.name = name;
this.healthTime = healthTime;
this.showHealth = function() {
console.log(this.name + "님, 오늘은 " + this.healthTime + "에 운동을 하셨네요");
}
}
const ho = new Health("crong", "12:12");
ho.showHealth();
4. prototype pattern
- constructor 패턴과 유사하나, 메서드를 prototype객체에 보관해서 constructor pattern보다는 메모리 효율 성에서 매우 유리하다.
const Health = function(name, healthTime) {
this.name = name;
this.healthTime = healthTime;
}
Health.prototype.showHealth = function() {
console.log(this.name + "님, 오늘은 " + this.healthTime + "에 운동을 하셨네요");
}
const ho = new Health("crong", "12:12");
ho.showHealth();
💡 prototype은 같은 클래스를 기반으로 만들기 때문에 각각의 객체의 메서드가 서로 같은 메모리 주소를 참조한다.
<prototype pattern을 사용해서 생성된 객체>
myHealth =>
name : "달리기",
lastTime : "23:10",
> __proto__ : Object
showHealth: ()
> __proto__: Object
- proto : prototype객체를 표현한 것
- prototype체인 : 모든 객체는 prototype으로 연결되어 있어, prototype안에 있는 어떠한 메서드를 사용하면, prototype을 타고 올라가면서 찾는다.
왜 prototype인가?
- prototype은 효과적으로 동작한다.
- 생성자를 통해 생성된 객체(인스턴스)들이 여러개 있어도, prototype에 연결된 객체들(movieObject)는 동일한 메모리 공간에서 효율적으로 재사용 된다.
- 즉, 두 객체의 prototype은 같다.
- prototype객체는 최상위 Object까지 연결되어 있기 때문에, prototype연결고리를 만들어서 객체간의 상속관계를 만들 수 있다.
5. Object.create
- 직접적으로 prototype키워드를 사용하진 않지만, Prototype object를 만드는 것과 동일하다.
- prototype기반 객체연결(상속형태)을 좀더 매끄럽게 사용하기 위해 탄생했다.
- ES6 Classes의 extend를 사용해서 이제 보다 쉽게 클래스간 상속 구조를 만들 수 있게 됐기 때문에 Object.create을 잘 사용하지 않는다.
const healthObj = {
showHealth : function() {
console.log(this.name + "님, 오늘은 " + this.healthTime + "에 운동을 하셨네요");
}
}
const ho = Object.create(healthObj, {
name: { value: "crong" },
healthTime: { value: "12:22" }
})
ho.showHealth();
object literal VS class
- object literal
- 여러개의 객체를 만들어서 생성할 필요가 없을때, 즉 일반화할 필요가 없는 경우에는 단순히 object literal로 객체를 표현한다.
- class
- 하나 이상으로 개별적인 객체를 생성해야 할 때 사용한다.