본문 바로가기

오늘 한 일을 기록하자/TIL

210114_TIL.. OOP에 대하여

오늘한 일

  • Object Oriented Programing 개념, 특징
  • Javascript 에서의 OOP 방법

 

OOP 란 객체지향언어를 사용하는 프로그램을 말한다(<-> 절차지향적언어).

대표적으로 객체지향언어로는 'Java'가 있고, 절차지향적언어에는 'c'가 있다.

 

1. 객체

객체지향언어에서는 모든게 객체이다.

즉, 프로그램을 구성하는 모든 요소(변수, 함수, 키워드 등)가 객체이다.

 

"객체지향이란 실세계를 직접적이고 직관적으로 모델링할 수 있는 패러다임"

...

객체란 인간의 인지 능력을 이용해 식별 가능한 경계를 가진 모든 사물을 의미한다.        - "객체 지향의 사실과 오해" [조영호]

 


객체 지향 프로그래밍(OOP: object-oriented programming)은 우리가 살고 있는 실제 세계가 객체(object)들로 구성되어 있는 것과 비슷하게, 소프트웨어도 객체로 구성하는 방법이다. 실제 세계에는 사람, 텔레비전, 세탁기, 냉장고 등의 많은 객체가 존재한다. 객체들은 객체 나름대로의 고유한 기능을 수행하면서 다른 객체들과 상호 작용한다. 
               - "어서와 Java는 처음이지!" [천인국]


 

객체는 속성(property) 과 기능(method) 을 가지고 있다.

 

 

 

2. Ebcapsulation(캡슐화)

다른 사람이 작성한 코드를 쓰기 위해서는 코드 자체가 잘 정리되어 있어야만 할 것이다. 관련된 데이터와 알고리즘이 하나의 묶음으로 정리되어 있어야한다. 이것을 '캡슐화'라고 한다.

 

 

2. Inheritance(상속)

코드의 재사용성을 높이기 위한 방법으로, 이미 작성된 부모 클래스를 이어받아서 새로운 자식 클래스를 생성하는 방법이다. 자식 클래스는 부모 클래스의 모든 속성과 기능을 물려 받을 수 있다.

추가로 만약 자식 클래스에만 필요한 기능이 있다면 추가 또는 변경할 수 있다.

다른 사람이 만든 클래스가 내 코드에서는 맞지 않는 경우가 종종 있다. 이런 경우에 상속을 사용해 다른 사람의 클래스를 상속받은 후에 자신이 필요한 부분을 변경하여서 사용할 수 있다. "상속은 기존의 코드를 재사용하는 강력한 기법이다"

 

 

3. Abstraction(추상화)

불필요한(복잡한) 정보는 숨기고 중요한 정보만을 표현함으로써 프로그램을 간단히 만드는 기법이다. 예를 들어서 TV를 객체로 나타내는 작업을 생각해보면 TV에는 지금까지 우리가 축적한 엄청난 기술들이 들어 있을 것이다. 따라서 TV를 객체로 나타내려면 객체가 엄청나게 커져야 할 것이다. 하지만 이래서는 프로그램하기 힘들어진다. 우리가 필요한 몇 개만을 남기고 불필요한 것들은 삭제하거나 숨겨야할 필요성이 있다.

전원 버튼을 누르면 TV가 켜지고 채널 버튼을 누르면 채널이 변경되는 기능만 있다고 가정할 수 있다. 이것이 바로 추상화이다.

추상화는 복잡성을 관리하는데 사용된다.  -> 추상화를 사용하지 않는다면 객체들이 너무 복잡해질 수 있다.

 

 

 

4. Polymorphism(다형성)

다형성이란 객체가 취하는 동작이 상황에 따라서 달라지는 것을 의미한다.

Polymorphism 은 "많은(poly) + 모양(morph)" 이라는 의미이다.

다형성을 사용하게 되면 실제 동작은 다르더라도 개념적으로는 동일한 작업을 하는 메소드들에 똑같은 이름을 부여할 수 있으므로 코드가 더 간단해질 수 있다.

예를 들어서 speak() 라는 메소드는 모든 객체 타입마다 정의되어 있어서 호출하면 객체가 소리를 발생한다.

 

speak() 를 호출 받은 객체는 자신의 상황에 따라서 서로 다른 소리를 내게 된다.

이처럼 객체들의 타입(클래스)이 다르면 똑같은 메시지가 전달되더라도 서로 다른 동작을 하는 것을 말한다.

즉 똑같은 명령을 내리지만 객체의 타입이 다르면 서로 다른 결과를 얻을 수 있는 것이 "다형성"이다. 여기서 중요한 점은 메시지를 보내는 측에서는 객체가 어떤 타입인지 알 필요가 없다는 점이다. 실행 시간에 객체의 타입에 따라서 자동적으로 적합한 동작이 결정된다.

한 곳에 모인 동물들이 각자의 소리를 내게 하고 싶으면 어떤 동물인지 신경 쓰지 말고 무조건 speak 메시지를 보내면 된다. 이 메시지를 수신한 동물은 자신이 낼 수 있는 소리를 낼 것이다.

 

 

 

Instantiation Patterns

1. Functional

let Car = function() {
  let someInstance = {};
  someInstance.position = 0;
  someInstance.move = function() {
    this.position += 1;
  }
  return someInstance;
};


let car1 = Car();
let car2 = Car();
car1.move();

 

 

 

2. Functional Shared

let extend = function(to, from) {
  for (var key in from) {
    to[key] = from[key];
  }
};

let someMethods = {};
someMethods.move = function() {
  this.position += 1;
};

let Car = function(position) {
  let someInstance = {
    position: position,
  }
  extend(someInstance, someMothods);
  return someInstance;
}

let car1 = Car(5);
let car2 = Car(10);

 

>> 1번 Functional 과 차이점은 무엇일까? 

Functional 방식은 인스턴스를 생성할 때 마다 모든 메소드를 someInstance 에게 할당하고 있다.

따라서 각각의 인스턴스들이 메소드의 수 만큼의 메모리를 더 차지하고 있다.

하지만 Functional Shared 는 someMethods 객체에 있는 메소드들의 메모리 주소만을 참조하기 때문에 메모리 효율이 좋아진다.

 

 

 

3. Prototypal

let someMethods = {};
someMethods.move = function() {
  this.position += 1;
}

let Car = function(position) {
  let someInstance = Object.create(someMethods);
  someInstance.position = position;
  return someInstance;
};

let car1 = Car(5);
let car2 = Car(10);

Object.create 는 특정 객체를 프로토타입으로 하는 객체를 생성해주는 함수이다[mdn 참고 문서].

 

 

4. Pseudoclassical  []

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

Car.prototype.move = function() {
  this.position += 1;
};

let car1 = new Car(5);
let car2 = new Car(10);

가장 많이 쓰는 방식이니 꼭 숙지하자

 

 

 

Inheritance Patterns

 

Prototype   &&   Constructor   &&  __proto__

Javascript 에서 말하는 Prototype 은 1. Prototype Object2. Prototype Link 가 있다.

1. 자바스크립에서 말하는 Prototype ??

function Test() { };

let jsPrototype = new Test();

console.log(jsPrototype);

 

__proto__ 는 jsPrototype 라는 객체를 만들어내기 위해 사용된 객체 원형에 대한 숨겨진 연결이다(= Prototype Link이다). 해당 객체의 프로토타입은 Test() 라는 함수 객체이며, constructor 는 이 객체의 생성자 역시 function Test() 함수라는 것이다.constructor 자격이 부여되면 new 키워드를 사용할 수 있다. 즉 new 를 통해 만들어진 객체는 function Test() 를 프로토타입으로 사용하여 만들어졌다는 말이다.

프로토타입은 자기 자신을 생성하게 한 자신의 원형 객체이다.

자바스크립트의 모든 객체는 생성과 동시에 자기자신이 생성될 당시의 정보를 취한 Prototype Object 라는 새로운 객체를 Cloning 하여 만들어낸다. 객체는 언제나 함수로 생성된다.

// 1. 객체 생성
function Test() { }
let obj = new Test();


// 2. 객체 생성
let obj1 = { };


// 3. 객체 생성
let obj2 = new Object();

 

프로토타입이 객체를 만들어내기 위한 원형이라면 이 Prototype Object 는 자기 자신의 분신이며, "자신을 원형으로 만들어질 다른 객체가 참조할 프로토타입"이 된다. 즉, 객체 자신을 이용할 다른 객체들이 프로토타입으로 사용할 객체가 Prototype Object 인 것이다.

__proto__ 라는 prototype 에 대한 link 는 상위에서 물려받은 객체의 프로토타입에 대한 정보이다.

prototype 프로퍼티는 자신을 원형으로 만들어질 새로운 객체들에게 하위로 물려줄 연결에 대한 속성이다.

 

function TV() { 
  this.channel = 300;
  this.volume = 100;
}

let samsungTV = new TV();
let lgTV = new TV();

console.log(samsungTV.channel);  // => 300
console.log(samsungTV.volume); // => 100

console.log(lgTV.channel);  // => 300
console.log(lgTV.volume); // => 100

 

위에서 samsungTV 와 LgTV 는 channel 과 volume 를 공통적으로 가지고 있다.

이 방법대로면 메모리에는 channel 과 volume 각각 두 개씩 총 4개가 할당된다.

이런 문제를 해결할 수 있는 방법이 프로토타입이다.

 

function TV() { }

TV.prototype.channel = 300;
TV.prototype.volume = 100;

let samsungTV = new TV();
let lgTV = new TV();

console.log(samsungTV.channel);  // => 300
console.log(samsungTV.volume); // => 100

console.log(lgTV.channel);  // => 300
console.log(lgTV.volume); // => 100

 

TV.prototype 의 속성을 추가함으로써 TV 함수로부터 생성된 객체(samsungTV, lgTV)들은 이 값을 참조할 수 있다.

 

 

2. Prototype Link

 

 

samsungTV 와 lgTV 에는 분명히 channel, volume 라는 속성이 없는데도 정상적으로 실행되는 모습을 확인할 수 있다.

이건 samsungTV 와 lgTV 가 가지고 있는 __proto__ 가 그것을 가능하게 해주고 있다.

__proto__ 속성은 모든 객체가 빠짐없이 가지고 있는 속성이다.

 

 

 

 

객체가 생성될 때 조상이었던 함수의 Prototype Object 를 가리킨다. samsungTV 와 lgTV 는 TV 함수로부터 생성되었으니 TV 함수의 Prototype Object 를 가리키고 있다.

channel 과 volume 를 직접 가지고 있지 않기 때문에 그 속성을 찾을 때 까지 상위 프로토타입을 탐색한다.

최상위인 Object 의 Prototype Object 까지 도달했는데도 못찾았을 경우에는 undefined 를 리턴한다.

이렇게, __proto__ 속성을 통해 상위 프로토타입과 연결되어있는 형태를 prototype chain 이라고 한다.

 

 

3. ES6 에서 OOP

class Shape {
  constructor(name, x, y) {
    this.name = name;
    this.x = x;
    this.y = y;
  }
  
  draw() {
    console.log(this.name + 'is Draw!!');
  }
}




class Rectancle extends Shape {

  constructor(name, width, height) {
    super(name, width, height);
  }
  
  area() {
    console.log(this.name + ' 의 넓이는 ' + this.x * this.y + '이다.');
  }
}


let rect = new Rectancle('사각형', 10, 20);


rect.area();
rect.draw();

 

 

 

 

Reference

 

[ES6] ES6 Syntax 정리

우리가 흔히 javascript 에서 ES5 혹은 ES6 라 부르는 것은 ECMAScript의 줄임말이며, MDN에 따르면 “ECMAScript는 자바스크립트의 토대를 구성하는 스크립트 언어입니다.” 라고 합니다. ES8, 9 등 여러 앞선

velog.io

 

 

[Javascript ] 프로토타입 이해하기

자바스크립트는 프로토타입 기반 언어라고 불립니다. 자바스크립트 개발을 하면 빠질 수 없는 것이 프로토타입인데요. 프로토타입이 거의 자바스크립트 그 자체이기때문에 이해하는 것이 어렵

medium.com

 

 

Javascript 기초 - Object prototype 이해하기 | Insanehong's Incorrect Note

소개 이번 글에서 다룰 내용은 자바스크립트의 프로토타입 상속(prototypal inheritance) 이라는 확장과 객체의 재사용을 가능하게 해주며 class 기반으로 인스턴스를 생성하지 않는 자바스크립트에서

insanehong.kr

 

'오늘 한 일을 기록하자 > TIL' 카테고리의 다른 글

210128_TIL... bind()  (0) 2021.01.28
210119_TIL.. 자료구조(Stack, Queue)  (0) 2021.01.19
210113_TIL  (0) 2021.01.13
201209_TIL  (0) 2020.12.09
201203_TIL  (0) 2020.12.03