Object Oriented Programming

서정욱 [marvin]·2021년 4월 23일
0

미리 말하지만 나는 객체지향을 싫어한다. 왜냐면 공부하면 할수록 더 좋은 패러다임이 많고 이에 동의하는 사람들이 존재하기 때문이다.

객체 지향 프로그래밍은 캘리포니아에서만 나올 수 있는 것 중 이례적으로 나쁜 아이디어입니다.
(Object-oriented programming is an exceptionally bad idea which could only have originated in California.)
— Edsger W. Dijkstra

그럼에도 불구하고 객체지향을 모르는 것은 허용하고 싶지 않다.

어떠한 언어는 객체지향을 기본 패러다임으로 만들어진 언어도 있고 (자바나.. C#같은…)
의도하지 않더라도 현실과 많이 닮은 점들이 있기 때문에 코드를 짜다보면 자연스럽게 객체를 짜고있기 때문이다.

자바스크립트 세계관에서는 객체지향이 어떻게 사용되는지 알아보자

객체 (Object)

객체는 무엇인가. 현실의 어떠한 물체를 생각해보자
현실의 어떠한 물체는 속성이 있고. 기능이 있다.

무게는 100g 정도 됩니다.
색상은 은색입니다.
소재는 철과 나무입니다.
모양은 대체로 길고 뾰족한 모양입니다.
손잡이를 가지고 있습니다.
이름은 식칼이라고 부릅니다.
무게는 100g 정도 됩니다.색상은 은색입니다.소재는 철과 나무입니다.모양은 대체로 길고 뾰족한 모양입니다.손잡이를 가지고 있습니다.이름은 식칼이라고 부릅니다.

이것은 속성이다.

벨 수 있습니다.
찌를 수 있습니다.
자를 수 있습니다.
손잡이를 이용하여 누를 수 있습니다.
벨 수 있습니다.찌를 수 있습니다.자를 수 있습니다.손잡이를 이용하여 누를 수 있습니다.

이것은 기능이다.
말 그대로 객체는 속성과 기능을 가진 현실의 어떠한 물체를 본따서 컴퓨터에서 사용하려는 것이고, 이렇게 만들어진 것이 Object 인 것이다.

객체지향

앞서 설명한 Object를 만들었다면 이러한 Object를 적극 활용하여 프로그래밍을 하자는 패러다임..
객체지향에서는 이 객체를 적극적으로 활용하기 위하여 몇가지 객체의 특징들을 약속해놓았다.

객체지향의 특징

캡슐화 (Encapsulation)
추상화 (Abstraction)
상속 (Inheritance)
다형성 (Polymorphism)

캡슐화 (Encapsulation)

캡슐화하는 이유는 두가지다.

편의적인 면
보안적인 면
자 아무것도 없는 도마위에 원산지 라고만 쓰여있다.
이러면 당연히 무엇의 원산지인지 모르지 않을까?
그런데 식칼에 “원산지” 라고 쓰여있다.
식칼의 원산지일 것이라고 사람들은 연상하게 된다.
그래서 우리는 프로그래밍에서도 도마위에 식칼의원산지, 생선의원산지, 이런식으로 일일히 나열하는 것이 아닌.
생선을 만들고 그 안에 속성으로 원산지를 넣어주고,
식칼을 만들고 그 안에 속성으로 원산지를 넣어주어 캡슐화시킨다.
편리하지 않은가

그렇다면 보안적인 면은 어떨까?
이것이 정확히 몇%의 합금인지 남들에게 알리고 싶지 않다면, 사실 이것을 남들에게 상해를 입힐 수 있는 기능도 있다는 것을 알리고 싶지 않다면?
이것을 숨기고 그냥 난 식칼이야 요리할때 써. 라고 건네주는 것만으로도 충분히 이 Object의 역할은 달성하지 않았을까
Object 의 숨기고 싶은 면, 혹은 굳이 안보여 줘도 되는 면들을 캡슐화를 통해 숨길 수 있다

추상화 (abstraction)

객체에게 부탁한다. 이것좀 건네줘.
그런데 사실 이 건네준다는 게 엄청나게 복잡하다.

이두근을 이완시켜 펼치고.
다섯손가락 두번째마디들을 굽혀서 0.7J의 힘으로 누른 뒤
다시 이두근을 45 수축 시킨뒤 상체를 돌려 나를 바라봐.
그 이후 손을 펴서 나에게 건내줘.

더 쪼갤 수 있는데 그만 쪼개겠다.
하고싶은 말은 이것이다. 여기서 중요한 부분만을 추려낸다.
물건을 들고, 나를보고, 건내줘.

이두근을 이완시켜 펼치고.다섯손가락 두번째마디들을 굽혀서 0.7J의 힘으로 누른 뒤다시 이두근을 45 수축 시킨뒤 상체를 돌려 나를 바라봐.그 이후 손을 펴서 나에게 건내줘.더 쪼갤 수 있는데 그만 쪼개겠다.하고싶은 말은 이것이다. 여기서 중요한 부분만을 추려낸다.물건을 들고, 나를보고, 건내줘.

물건또한 마찬가지겠지.

사과가 대체로 빨갛지만. 
사실은 상단부분은 체리애플블라썸 색이고, 
중단부분은 베리베리스트로베리 색이고 하단부분은 로열레드 색이다.
근데 그냥 빨갛다고 부르겠다.

자 이게 추상화다. 일련의 복잡한 과정, 속성들을 축약하고, 간소화시키는 것.
이러한 추상화가 깊어질수록 우리는 이 복잡한 것을 간단하게 볼 수 있게 된다.

상속 (Inheritance)

상속은 생각보다 간단하다. 상속은 특히 웃긴게 무수히 많은 상속이 가능하다.

동물이 있다. 동물은 보통 이름이 있고, 생명활동을 한다.
해양동물이 있다. 해양동물은 동물의 속성과 기능을 모두 갖고 있으며, 서식지가 바다이다
갑각류가 있다. 갑각류는 해양동물의 속성과 기능을 모두 갖고 있으며, 피부가 단단하다.
어류가 있다. 어류는 해양동물의 속성과 기능을 모두 갖고 있으며, 아가미로 호흡한다.
참치가 있다. 참치는 어류의 속성과 기능을 모두 갖고 있으며, 지방질이 풍부하고 깊은곳에 서식한다.

정리해보자. 동물 > 해양동물 > 어류 > 참치
여기서 화살표가 상속 이다.
부모의 속성과 기능이 자식에도 존재한다.
주의해야 할점은. 부모가 자식때문에 필요없는 속성을 갖고 있지 않게 표현해야 하고.
상속하지 않고 같은 부모를 사용해야 할 때를 구분하는 것이다.
여기서는 갑각류와 어류같이 해양생물 정도만 공통적이고 나머지는 차이가 존재하기 때문에 추가 상속하지 않았다.

다형성 (Polymophism)

사람이라는 Object가 있다. 이 사람은 동물을 상속받았다.

사람.인사해()
헬로

예측된 결과다. 그럼 이번엔 개에게 시키겠다.

개.인사해()
헬로

응? 이러한 일이 발생하지 않게 같은 이름의 기능이라도 다르게 작동시킬 수 있게 해주는 특징이 다형성이다.

개.인사해()
멍
고양이.인사해()
야옹

다형성이 있어야 이러한 편리한 기능이 구현된다. 자바에서는 이를 구현하는 오버로딩과 오버라이딩이라는 방법이 있는데
여기서는 언급하지 않겠다.

인스턴스

자바에서는 클래스라는게 있다.

클래스는 공장에서 물건을 찍어내는 틀, 사진을 찍어내는 청사진과 같다.
우리가 식칼을 만들려고 한다. 그때마다 위에서 설명 한 속성과 기능들을 나열해야 한다면?

무게는 100g 정도 됩니다.
색상은 은색입니다.
소재는 철과 나무입니다.
모양은 대체로 길고 뾰족한 모양입니다.
손잡이를 가지고 있습니다.
이름은 식칼이라고 부릅니다.
벨 수 있습니다
찌를 수 있습니다.
자를 수 있습니다.
손잡이를 이용하여 누를 수 있습니다.

이런 물체를 만들어줘. 매번 이렇게 부탁할것인가?
자 이렇게 해보자
앞으로 내가 식칼클래스를 쓰면 항상 위에 나열한 속성과 기능이 담겨있어야 해.

자 그럼 사용해보자

식칼클래스로 식칼을 만들어줘.

여기서 만들어진 식칼이 인스턴스 라는거다.
즉 한개의 클래스로 많은 인스턴스를 만들수 있다.

그러면 자바스크립트에서는??

자바스크립트에서는 클래스가 아니라 함수로 인스턴스를 만든다

let instance = new Object();

함수를 실행했는데 인스턴스가 만들어졌다. 어떻게?
여기서 사용되는 게 prototype 이다 알아보자.

Prototype

자바스크립트 객체는 Prototype이라는 내부 프로퍼티가 존재한다.
prototype은 본인이 원래 가져야할 속성과 기능의 명세. 즉 클래스와 같은 역할을 하고 있다.

객체를 생성하면 자신이 상속받은 부모의 prototype은 __proto__ 속성에 연결한다.
이를 통해 자바스크립트의 모든 객체는 자신의 부모 역할을 담당하는 객체와 연결되어 있다.
이것은 프로토타입 링크 라고 하겠다.
특정 객체의 프로퍼티나 메소드에 접근하려고 할 때 해당 객체에 접근하려는 프로퍼티 또는 메소드가 없다면
__proto__이 가리키는 링크를 따라 자신의 부모 역할을 하는 프로토타입 객체의 프로퍼티나 메소드를 차례대로 검색한다.
이것을 프로토타입 체인이라 한다.

자 이건 알겠고 그렇다면 함수는?

함수를 정의하면 함수만 생성되는 것이 아니라 Prototype Object도 같이 생성이 된다.
Prototype Object는 constructor__proto__를 가지고 있다.
constructor는 함수인데. 이 함수는 만들어질 객체가 가져야할 property들이 정의되어 있다.
new 키워드와 함께 함수를 호출할 경우 constructor함수를 실행하고 __proto__ 를 부모의prototype과 연결한다.
new로써 만들어진 모든 객체는 결국 부모.prototype 과 __proto__ 링크로 연결된다는 것이다.

결과적으로 이렇게 된다.

instance.__proto__ === Object.prototype // true

인스턴스를 만드는 방법 실습

functional

const Human = function() {
  const instance = {};

  instance.name = 'functional instantiation';
  instance.func = function() {
    console.log("기능입니다.")
  };

  return instance;
}

let instance = Human();

instance.name;
// functional instantiation

instance.func();
// 기능입니다.
functional shared
const extend = function(to, from) {
  for (let key in from) {
    to[key] = from[key];
  }
};

const sharedFunc = {};
sharedFunc.say = function(hi) {
  this.say = hi;
}

const Human = function() {
  const instance = {};

  instance.name = 'functional shared instantiation';
  instance.func = function() {
    console.log("기능입니다.")
  };
  extend(instance, sharedFunc);

  return instance;
}
let instance = Human();

instance.name;
// functional shared instantiation

instance.func();
// 기능입니다.

instance.say("hello");
instance.say;
// hello

prototypal

const method = {};
 method.say = function(hi) {
   this.say = hi
}

const Human = function() {
  const instance = Object.create(method);

  instance.name = 'prototypal instantiation';
  instance.func = function() {
    console.log("기능입니다.")
  };

  return instance;
}

const instance = Human();

instance.name;
// prototypal instantiation

PseudoClassical

const Human = function(hi) {
  this.say = hi;
}

Human.prototype.bye = function() {
  console.log("bye bye")
}

const instance = new Human("hello");

instance.say;
// hello

instance.bye();
// bye bye
profile
JavaScript 개발자입니다

0개의 댓글