[TIL]OOP(Object Oriented Pattern)에 대해

Violet Lee·2020년 10월 28일
0

javascript

목록 보기
22/24

Programming Language

기본적으로 컴퓨터 시스템을 구동시키는 소프트웨어를 작성하기위한 형식 언어이다.
이 프로그래밍 언어는, 보통 저급 언어, 고급 언어로 분류되며,
보통 유연하고 이식성이 좋을수록 고급언어로 분류된다.

  • 기계어 -> 하이레벨언어
    : 유연성 ↑ 구현이 용이해짐. 이식성 ↑. 그렇지만 컴파일하는 과정에서 좀 속도가 ↓
  • 하이레벨언어 -> 기계어
    : 코드가 짧아짐. 속도가 ↑. 특정머신에 종속화.

- low-level language

  • machine language
    : 1과 0으로 조합된 언어. 프로그램들을 기계어로 작성하기 시작함.
    10진이나 2진 형태의 프로그램들을 작성하는데 쓰이는 1세대 프로그래밍 언어이다.

  • assembly language
    : 기계어와 1 : 1 대응이 되는 2세대 프로그래밍이다.

    • 속도 ↑
    • CPU에 종속적이다.

- high-level language

: line by line으로 읽으면서 바로 컴파일을 하여 컴퓨터가 인식할 수 있게 해준다.
객체지향적 언어와 절차지향적 언어가 있다.

  • 절차지향적 언어

    • 어떤 절차로 이 언어들이 이어지게할지 정하는게 절차지향적. 코볼 등..
  • 객체지향적 언어

    • 추상적인 것을 포함해서 모든 변수나 함수등을 객체로 만든 언어.
      ex) c++, c#, java, python, js, ruby, swift, object-c ...

- Object Oriented Programming

: 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나,
여러개의 독립된 단위, 즉 '객체'들의 모임으로 파악하고자 하는것을 말한다.
이 각각의 객체들은, 메시지를 주고받고, 데이터를 처리할 수 있다.

  • 이전 절차적 프로그래밍과는 다른 프로그래밍 언어를 사용.(객체지향적)
  • 추상적인 것을 포함해서 모든 변수나 함수등을 객체로 그룹화함.

OOP의 4가지 주요 객체지향 프로그래밍 개념

  • OOP에 사용하는 것들
    • class : 클래스는 객체를 만들기위한 프로토 타입, 아이디어 및 청사진.
      • 클래스에는 객체를 생성하기위한 생성자가 있음.
    • object : 클래스를 상속한 것.

1) encapsulation : 캡슐화.
2) inheritance : 상속. 부모의 특징을 자식이 물려받는다.

ex01)

mdn HTMLDivElement 를 검색해서 보면,
eventTarget <- node <- element <- HTMLElement <- HTMLDivElement 순으로,
즉 오른쪽에서 왼쪽으로 부모를 가지고 있는걸 볼 수있다.
즉 이 경우는 eventTarget이 가장 위의 부모이며, HtmlDivElement가 가장 아래의 자식임을 알 수 있다.

ex02)

car라는 class가 있다하면, 그 차들이 공통적으로 갖고있는 속도, 컬러등의 속성, 메소드들을 내부에서 정의하여, 객체화 시킴.


3) abstraction
: 추상화. 우리는 예를들어, 전화기가 어떻게 이루어져있는지 자세히 알 필요는 없지만, 그 기능을 사용한다.

4) polymorphism : 다형성.

          switch(...){
          	case 'select' : renderSelect();
          	case 'text' : renderTextBox();
          	case 'checkBox' : renderCheckBox();
          	case ...
          	case ...
          	case ...
          }
ex) HTMLElement는 testbox, select, checkbox 등의 부모이다.
    만약 OOP가 이 다형성을 갖고있지 않다면, 위의 예시를 구현할 시에, 
    이렇게 일일이 써야할 것이다.
         
    위의 코드는 즉, 'select'를 선택할 시에, renderSelect()를 호출해와야 하고,
    'text'를 선택할 시에, renderTextBox()를 호출해와야하고,
    'checkBox'도 마찬가지로 그에 맞는 함수를 호출해와야하고...
    
   

JavaScript에서 Object를 생성하는 여러가지 방법들

일단, class를 언제 사용하나?

: class는 하나의 정형화된 모델을 만들어두고, 그 모델을 기반으로 한 인스턴스(복제품)를 만들기위해 사용한다.
마치 공장에서 같은 규격의 제품을 찍어내는것과 비슷하다고 보면 된다.

예를들어 Car라는 객체는 항상 position이라는 속성, move라는 메소드를 갖는다고 가정해보자.
그리고 car1, car2, car3 ... 매우 많은 car들을 사용하는 프로그램들을 작성한다고 할때,
많은 car들을 하나하나 변수로 선언해주는것은 많은 시간을 필요로 할 것이다.😂

=> 그렇기때문에, 우리는 이 car라는 모델을 하나 생성해둔뒤, 그 모델들을 복사하여 찍어내면 편하겠지?
=> 그리고 그 기능은 함수를 이용해서 표현이 가능하다고 한다!

1. functional

먼저 functional instantiation(함수 객체화)방식으로 우리들의 자동차공장을 만들어본다.

예제01) position의 기본 초깃값이 0 일때.

var Car = function(){
    var someInstance = {}; //1. 이 함수 실행시, 찍어내 줄 객체선언.
                            //물론, return을 해줘야 함수의 결과로 객체가 나온다.
    someInstance.position = 0; //2. someInstance의 posiiton을 0으로 초기화시켜줌.
                                //0이 아니라 만약 = position을 쓴다면, 나중에 이 함수 호출시 인자로 넣어준값이 
                                //position의 기본 초깃값이 될거임!
                                //우선, Car함수가 실행되어서 나온, 인스턴스의 position 초깃값을 0으로 지정.
    someInstance.move = function(){ //3. someInstance에 move메소드 추가. 이 함수 내부의 this는
                                    //someInstance 자체를 뜻하므로, this.position은 someInstance.position과
                                    //같고, 4. 함수 실행시(아니면 메소드실행시..? 1 증가될것이다. 포지션이)
        this.position += 1;
    }
    return someInstance;
};
var car1 = Car();
var car2 = Car();
car1.move(); //5. 이제 car1.move()를 실행한 뒤에, car1을 콘솔로그로 찍어보면,함수 내부에서 position이 1 증가된걸 확인해볼수있다.
console.log(car1);

예제02) position의 기본 초깃값을 지정해줄때.

var Car = function(position){
    var someInstance = {}; //이 함수 실행시, 찍어내 줄 객체선언.
                            //물론, return을 해줘야 함수의 결과로 객체가 나온다.
    someInstance.position = position; //someInstance의 posiiton을 0으로 초기화시켜줌.
                                //0이 아니라 만약 = position을 쓴다면, 나중에 이 함수 호출시 인자로 넣어준값이 
                                //position의 기본 초깃값이 될거임!
                                //Car함수가 실행되어서 나온, 인스턴스의 position 초깃값은 항상 0일 것임.
    someInstance.move = function(){ //someInstance에 move메소드 추가. 이 함수 내부의 this는
                                    //someInstance 자체를 뜻하므로, this.position은 someInstance.position과
                                    //같고, 함수 실행시(아니면 메소드실행시..? 1 증가될것이다. 포지션이)
        this.position += 1;
    }
    return someInstance;
};
var car1 = Car(5);
var car2 = Car();
car1.move(); //이제 car1.move()를 실행한 뒤에, car1을 콘솔로그로 찍어보면,함수 내부에서 position이 1 증가된걸 확인해볼수있다.
console.log(car1);

2. functional shared

var extend = function(to, from){ //3. 그리고, someInstance와 someMethods를 합치는 extend함수를 만들어서,
                                //Car내부에서 합쳐줌 ㅇㅇ.
    for(var key in from){        //to는 someInstance, from은 someMethods가 되어서,
                                //임시적으로 기본 객체내부의 속성값을 변화시켜서 저장해놓을 someMethods의 속성들을
                                //돌면서, 실제 리턴할 someInstance의 속성값으로 someMethods의 호출값을 할당함.
        to[key] = from[key];
    }
}

var someMethods = {}; //2. 그리고 method를 담아줄 어떤 객체 생성하여..
                      //모든 메소드를 someMethods에 담을것임.일단 담을 메소드는 move 당장 하나지만! 
                      //이 move메소드는, 호출시 이 move메소드내에서 position을 1 증가시켜줄꺼임.
someMethods.move = function(){
    this.position += 1;
}

var Car = function(position){ //1. 먼저 car함수선언. 바로 position을
                             //someInstance의 property로 넣어준것 외에는 아직까지 그냥 functonal과 다른부분 x.
    var someInstance = { //이거는 들어오는 position 인자값을, position속성의 값으로 바로 할당할 객체 준비해놓은 거임.
        position : position,
    };
    extend(someInstance, someMethods); //4. 이후 extend함수를 부모함수 Car에서 호출하여, 리턴용객체, 호출값변경겍체를
                                        //인자로 넣어줌.
    return someInstance;
}
var car1 = Car(5);
var car2 = Car(10);
car1.move(); //앗! 이건 someMethods 객체 내부의 함수잖아요? > Car를 부모로 extend함수를 내부에서 호출시켰으므로 그 값이 
              //마지막에 someInstance에 들어오게 되어, 리턴할시에 move()를 사용한 값이 반영될것이다.
console.log(car1); //position: 6

왜 이렇게 번거로운 방식으로 값을 변화시켜 사용할까?

: 이전의 functional방식은 인스턴스 생성시, 모든 메소드를 someInstance에게 할당했으므로,
각각의 인스턴스들이 메소드의 수 만큼, 메모리를 더 차지했기떄문.
약간 다중 스레드를 만들기이전에 프로그램을 여러개 생성했을때와 같이 보면 이해될것같다.

그러나 이 방식을 사용한다면,
someMethods라는 객체에 있는 메소드들의 메모리 주소만을 참조하기 때문에,
메모리 효율이 훨씬 증가할 것임.


3. prototypal Instantiation

var someMethods = {}; //먼저 functional shared방식과 비슷하게 코드 작성.
                      
someMethods.move = function(){
    this.position += 1;
}
var Car = function(position){ 
                             
    var someInstance = {};
    someInstance.position = position;
    
    return someInstance;
}

var someMethods = {}; //먼저 functional shared방식과 비슷하게 코드 작성.
                      
someMethods.move = function(){
    this.position += 1;
}
var Car = function(position){ 
                             
    var someInstance = Object.create(someMethods); //이렇게만 바꿔주면 끝.
    //Object.create(): 특정객체를 프로토타입으로 하는 객체를 생성해주는 함수.
    someInstance.position = position;
    
    return someInstance;
}
var car1 = Car(5);
var car2 = Car(10);
car1.move(); 
console.log(car1); //position: 6

4. pseudoclassical

  • Prototype :
    자바스크립트의 모든 객체는 자신의 부모 역할을 담당하는 객체와 연결되어 있다.
    그리고 이것은 마치 객체 지향의 상속 개념과 같이
    부모 객체의 프로퍼티 또는 메소드를 상속받아 사용할 수 있게 한다.
    이러한 부모 객체를 Prototype(프로토타입) 객체라고 한다!

Prototype 객체는 생성자 함수에 의해 생성된 각각의 객체에 공유 프로퍼티를 제공하기 위해 사용한다.

var Car = function(position){ 
                             
    this.position = position;
}
Car.prototype.move = function() { //이렇게 move메소드를 Car함수의 프로토타입으로 체이닝해줌. 그럼 끝! ㅋㅋ
    this.position += 1;
}
var car1 = new Car(5); //하지만 찍어낼때에 new operator를 붙여야 함. 그냥 실행시 안의 move메소드를 찾을수없다는 에러발생!
var car2 = new Car(10);
car1.move(); 
console.log(car1); //position: 6
profile
예비개발자

0개의 댓글