Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

coding etude

200909 [OOP : Object-Oriented Programming] 본문

Javascript TIL

200909 [OOP : Object-Oriented Programming]

코코리니 2020. 9. 9. 17:29

OOP (Object-Oriented Programming)

 : 사전적 의미 그대로 객체 지향 프로그래밍의 약자로 명확히 정의된 의미는 없다.

하지만, 객체 지향의 특성을 통하여 객체지향의 의미를 알 수 있다.

객체 지향 프로그래밍이란 실세계에 존재하는 모든 것(객체)을 가상의 프로그램의 세계에 구현하기 위해 객체의 특징적인 개념 또는 기능들을 추상화(abstraction)작업을 통하여 간결하게 만들어 내는 프로그래밍의 한 형식이라고 할 수 있다. (abstraction 을 통한 encapsulation을 실행하는것)

*지향의 사전적 의미 : 그것(객체구현)을 실현하는  필요한 수단과 예상되는 결과의 관념을 이르는 

 

    객체지향 언어는 이전의 컴퓨터 친화적인 언어에 가까운 절차지향 프로그래밍과 다르게 인간 친화적인 언어로 유연하고 유지보수가 쉬우며 보다 자유로운 언어이다. 보통의 객체 지향 프로그램은 class 를 기반으로 한 것이 많지만 Javascript 에서는 ES6 에서 class 가 추가 되었고 그 이전에는 prototype 기반의 객체지향 언어였다. 이 글에서는 Javascript를 기준으로 하여 객체지향을 설명 하려고 한다.

 

▶class vs. prototype 

 : 클레스란 같은 집단에 속해있는 속성(arrtibute)과 행위(behevior)를 정의한 객체지향의 기본적인 데이터의 정의형태이다. 다시말해 클레스는 객체를 정의하기 위한 패턴 또는 설계도라고 할 수 있고 이것을 생성자를 사용하여 인스턴스(instance)화 시켜야 사용 할 수 있는 것이다. 모든 인스턴스들은 클레스의 정의된 범위를 벗어 날 수 없고 그 구조를 변경 할 수 없다. 이러한 클레스의 특성으로 말미암아 안정성, 정확성, 예측성이 우수하다.

 

반면, Javascript는 프로토타입 기반의 언어로 다른 객체지향 언어와는 체계가 다르지만 객체지향의 강점을 가지고 있다.

Javascript 에서 class 라는 개념이 나오기 전에도 별도의 인스턴스화 진행 방법(객체 생성 방법을 이용한)이 존재한다.

// 객체 생성 방법
let obj = {};
obj.name = 'kim';  // {name : 'kim'}

// Object 생성자
let obj = new Object();
obj.name = 'kim'; // {name : 'kim'}

// 함수 생성자
function fn(){}
let obj = new fn();
obj.name = 'kim';

 

 

1. function instantiation (함수를 사용한 인스턴스화)

 : 함수 내에 빈 객체를 형성하여 값을 저장 후 외부에서 실행 시 값이 실행 되면서 작동 되게끔 하는 방식.

 ( 메모리의 소모가 크다는 단점이 있다.)

let car = function(){
		let instance = {}; 
        instance.position = position; 변화값
        instance.move = function(){  // 조건
        	this.position++;
            }
         return instance;   
	}
    
    // let car1 = car(value); 의 방법으로 사용
    // value 값에 의해 position의 값이 변함.

2. function shared (함수 공유)

 : 외부 메소드에 함수의 값을 편화 시킬 조건을 선언 후 함수에 변화 시킬 객체를 생성하고 외부의 메소드를 참조하여 실행하는 방식 (메모리의 소모가 적다.)

let extend = function(to, from){ // 외부의 객체와 메소드의 값을 받아서 실행
	for(let key in from){ 
    to[key] = from[key];
    }
   }

let car = function(){  // 객체
		let instance = {position : position}; 
        extend(instance, method) // 넘겨줄 값
        return instance;
	}

let method = {}; // 실행 조건
method.move = function(){
	this.position++
	}
    // let car1 = car(value); 의 방법으로 사용
    // value 값에 의해 position의 값이 변함.

3. prototype instantiation(프로토타입을 사용한 인스턴스화)

 : 프로토타입 instantiation(inheritance)은 Object.create를 사용하여 객체에서 다른 객체로 직접 상속을 구현하는 방식이다

let car = function(){  // 객체
		let instance = Object.create(method) // 프로퍼티의 오브젝트의 속성을 참조하여 외부 메소드를 생성
        return instance;
	}

let method = {}; // 실행 조건
method.move = function(){
	this.position++
	}
    // let car1 = car(value); 의 방법으로 사용
    // value 값에 의해 position의 값이 변함.

4. pseudoclasscal 

 : 자식 생성자 함수의 prototype property를 부모 생성자 함수의 인스턴스로 교체하여 상속을 구현하는 방법이다.(pseudoClass Inheritance)

let car = function(position){
		this.position = position;
	}

car.porototype.move = fubction(){
  		this.position++;
    }
    
    // let car1 = new car(value) 참조할때마다 new 생성자를 사용해야 한다.

 

★ 중요!!(Prototype)

위의 예제를 이해하려면 prototype을 어느정도 이해해야 한다. 그래서 잠깜 프로토 타입에 대해 이야기 해본다.

prototype 은 class 가 없는 Javascript에서 class의 상속 기능을 사용하게 만들어준다. 물론 ECMA6 에서 class문법이 추가 되었지만, Javascript가 클레스 기반으로 바뀐것은 아니다.

일반적으로 프로토타입은 원형이라는 의미를 가진다. 즉, 자바스크립트에서의 원형은 자신을 만들어낸 객체의 원형을 뜻하는데 반대로 생각해서 앞으로 만들어질 객체의 원형이라고 생각한다면 결국 프로토타입은 객체의 모든 특성(property)을 사용 할 수 있게 해주는 것이다. (부모객체의 속성을 모두 사용 할 수 있는것과 같다고 생각하면 된다.)

ex) car.prototype.move => 객체(Object)내에 존재하는 move를 사용 할 수 있다는 말이 된다.

 

prototype Link 와 prototype Object

 : 프로토타입에는 두가지의 이 특성(property)이 존재하는데 prototype Link / prototype Object 이다.

 

1. prototype Object

let obj = {};

let obj = new Object();

 : Javascript에서 객체는 언제는 함수로 생성이 된다. 위 두 예제는 같은 코드라고 볼수 있는 것이다. obj 는 Object의 속성을 참조하여 만들어 진다고 볼 수 있고, 결국 Object 는 Javascript가 제공하는 기본적인 함수라고 생각 할 수 있다.

Object 와 마찬가지로 Function / Array 도 역시 기본 함수로 구현 되어 있다.

 

이처럼 함수가 정의 될 때 함수에 생성자(constructor)의 자격이 부여되면서, 동시에 prototype Object 가 생성이 돤다. 그래서 생성자의 자격이 부여되면서 new를 사용하여 객체를 만들어 낼수 있는 것 이다.

let obj = new Object(); // true;

let Obj2 = new obj() // type error : obj is not a contructor..

또한, 결국 함수가 생성이 되면서 prototype Object가 동시에 생성이 되기 때문에 함수 내부의 prototype으로 접근이 가능해 지는 것이다.

함수 생성 시 prototype Object 의 생성

그렇기 때문에 함수가 prototype Object에 접근을 하면 prototype Object가가지고 있는 cunstructor / __proto__를 사용 할 수 있게 되는 것이고 이 속성중에 __proto__ 가 prototype Link 인 것이다.

 

★__proto__

@ 모든 객체가 가지고 있는 속성.
@ prototype 는 상위 속성에 접근하여 사용 가능하게 하지만 __proto__는 모든 객체개 가지고 있기 때문에 
Object.prototype 에 접근 하여 사용 가능하게 해준다.

 

2.prototype Link

let car = function() {}; 

car.prototype.tire = 4;
car.prototype.gear = 6;

car.tire = 4;
car.gear = 6; 

let tico = new car;
tico.tire = 4;

// 함수가 생성되고 함수의 prototype 에 tire / gear 의 값을 선언 했기 때문에 
// car로 생성된 tico 는 prototype Object 에 접근이 간으한 것이다.

위의 예시처럼 tico는 tire의 속성 없이 어떻게 prototype Object의 tire를 참조 할 수 있는것일까?

그 이유는 __proto__ 때문이다. prototype 는 함수만 가지고 있는 속성이지만 __proto__는 모든 객체가 가지고 있는 속성이기 때문에 생성된 tico는 __proto__를이용하여 원형중에 tire를 가지고 있는 객체를 찾고 있으면 그 값을 반환 하는것이다. (값이 없다면 undefined) 이런 타입 구조 때문에 모든 객체는 Object 의 자식으로 불릴 수 있으면서 Object prototype Object 에 있는 모든 속성을 사용 할 수 있는 것이다.

(prototype link(프로토타입연결)가 prototype chain을 형성하게 해준다.)

프로토타입 체인 도표

 

▶Inheritance(상속) 

 : 상속이란 부모객체의 속성을 자식객체가 받아서 속성을 추가하여 확장(extend) 하는 개념을 가지고 있다.

class 기반의 객체지향에서는 class 를 상속시켜 instance 를 만들어 그 기능을 확장 시키거나 class 에서 다른 class를 extend 해서 속성을 사용 할 수 있게 하지만 Javascript에서는 크게 두 가지의 방법으로 class 상속방식을 흉내 낼 수 있다.

  • psedoclasscal inheritance
  • prototypal inheritace

★Object.create

간략히 하나를 추가 하자면 3번에서 말하는 Object.create지정된 프로토타입 객체 및 속성(property)을 갖는 새객체를 만든다 라고 MDN에 명시되어 있다. 이 말은 매개변수를 또는 매개변수의 속성을 갖는 새로운 객체를 만든다는 것이다. prototype 에서 설명했듯이 모든 객체의 __proto__는  Object를 향하고 있기 때문에 새로 생성되는 객체를 온전히 만들고 싶다면  Object.create 를 사용해야 하는 것이다. 만약 Object.create없이 바로 상속이 되어도 크게 문제는 없어지만 상속으로 만들어진 객체는 Object를 향하는게 아닌 상속자를 향하게 되어 새로운 객체의 기능에 제한이 된다는 점을 인지해야한다. 요약해서 말하자면 Object.create 없이 객체를 상속 생성하게 되면 생성되는 객체의 prototype.constructor = 상속자 가 된다.( 원래는 prototype.constructor = Object)

 

상속관련 예시는 instantiation 의 3번과 4번에서 설명 하였기 때문에 참고하면 된다.

 

 

 

▶polymorphism(다형성) 

 : 다형성이란 하나의 설계도(class or method)를 가지고 다양한 방법으로 동작 또는 제작 하는 것을 말한다.

이 과정을 정리하면 1:N 의 관계를 형성하는데 이것을 다형성이라고 한다.

보통 class 기반의 다형성은 선언부와 구현부가 명확하게 구분이 되어 지지만 Javascript는 엄격하게 구분되는 언어가 아니기 때문에 이러한 다형성을 prototype chain 을 이용하여 다양하게 구현 해 낼 수 있다. Javascript 에서는 객체의 생성과 사용이 어디서든 가능하기 때문에 상속의 개념을 정형화 하여 다형성을 구현해 낼 수 있는 것이다 .

 

▶Encapsulation (캡슐화)

 : 캡슐화는 관련있는 변수와 메소드등을 클레스와 같이 하나의 틀안에 넣고 외부의 접근을 막는것을 말하는데 Javascript에서는 이러한 엄격한 기준이 없다. 대신 Javascript는 scope 라는 범위의 개념을 가지고 있기 때문에 캘슐화가 가능하다. 하나의 블럭(객체, 함수, 메소드 등)을 기준으로 전역과 로컬의 범위를 가지면 이러한 규칙 안에서 Encapsulation이 이루어 진다고 생각하면 된다.

// scope 의 encapsulation 예
let var; // 전역 변수 

function fn(){ // 고차함수
	let var1; // function 내에서만 사용이 가능한 local 변수
	
    return function(){ // closer (내부함수)
    let var2 = var1 + var;
}

let var3 = new fn(x); // 함수를 이용한 instantiation(inheritance)
  // var3 은 fn()의 속성 사용이 가능하다.
  
  // scope를 이해하자!

 

※ 지금까지 OOP에 관하여 포스팅 해봤는데 하면서 느낀점은 아직 많이 부족하다는 것이다. 특히, prototypeproperty의 정확한 이해가 필요하기 때문에 두개의 주제는 따로 정밀한 포스팅을 할 예정이다.

'Javascript TIL' 카테고리의 다른 글

200927 [parse / parsing / JSON / json()]  (0) 2020.09.27
200910 [Linked List]  (0) 2020.09.10
200908 [자료구조 : Stack / Queue]  (0) 2020.09.09
200904 [ESlint]  (0) 2020.09.06
200903 [Prep]  (0) 2020.09.05