OOP ( 객체지향 프로그래밍)

katsukichi·2021년 2월 26일
0

CodeStates_IM

목록 보기
12/48

절차적 언어

  • 초기의 프로그래밍 언어는 일반적으로 절차적 언어라고 불렀다. C언어 ,포트란? 등등..
  • 절차적 언어는 순차적인 명령의 조합

객체지향 언어

  • "클래스"라고 부르는 데이터 모델의 청사진을 사용해 코드 작성
  • 현대의 언어들은 대부분 객체지향의 특징을 갖고 있음( 대표적으로 java,C++,c#등)
  • javascript : 객체 지향으로 작성 가능

자바스크립트는 엄밀히 말해 객체 지향 언어는 아니지만, 객체지향 패턴으로 작성할 수 있습니다.

OOP

  • OOP는 프로그램 설계 철학입니다.

  • OOP의 모든것은 "객체"로 그룹화 됩니다.

  • OOP의 4가지 주요 개념을 통해 재사용성을 얻을 수 있습니다.

클래스와 인스턴스

  • 클래스는 일종의 원형(original form)으로, 객체를 생성하기 위한 아이디어나, 청사진 입니다.

  • 인스턴스는 클래스의 사례(instance)입니다.

  • 클래스는 객체를 만들기 위한 생성자(constructor)함수를 포함합니다.

속성 , 메소드

고유 속성이 존재할수있고

기능으로 메소드가 존재합니다.

OOP Basic Concepts

  • Encapsulation / 캡슐화
  • Inheritance / 상속
  • Abstraction / 추상화
  • Polymorphism / 다형성

캡슐화 Encapsulation

데이터와 기능을 하나의 단위로 묶는것으로

은닉(hiding) : 구현은 숨기고 , 동작은 노출시킴

느슨한 결합(Loosing Coupling)에 유리: 언제든 구현을 수정할 수 있음

보다 엄격한 클래스는 속성의 직접적인 접근을 막고, 설정하는 함수(setter), 불러오는 함수(getter)를 철저하게 나누기도 합니다. (자바 언어의 경우)

추상화 Abstraction

실제로 노출되는 부분은 단순하게 만든다는 개념이다.

예를 들어 전화 라는 객체가 있다면, 그 안에 스피커와 마이크가 존재하고, 서킷보드 등이 존재하는 등 내부 구현이 되어 있을 것입니다.

추상클래스 같은 거 생각 나긴한다. 당연히 상속을 필수적으로 하게만드는 느낌도 없잖아있지만

껍데기 라는 느낌도 드는데. 이런느낌이 아마 C++에서 인터페이스 배울때 느낀 것같다.

추상화와 캡슐화가 헷갈리는 개념이다.

  • 캡슐화가 코드나 데이터의 은닉에 포커스가 맞춰져있다면, 추상화는 클래스를 사용하는 사람이 필요하지 않은 메소드 등을 노출시키지 않고, 기능 단순한 이름으로 정의하는 것에 포커스가 맞춰져 있습니다.

  • 클래스 정의 시, 메소드와 속성만 정의한 것을 인터페이스라고 부릅니다. 이것이 추상화의 본질입니다.

상속 Inheritance

상속을 받는다.

기본클래스(basis class)와 파생클래스(derive class)가 있다.

기본클래스의 내용을 파생클래스가 상속받아서 사용할수있는것이다.

파생클래스는 추가적인 기능을 더 가지고 있을수 있다.

쉽게 생각하면 3대가 상속을 받고있다면

할아버지보다 아버지가 할수있는일이 많을거고

아버지보다 아들이 능력이더 출중할것이다.

(이론상으로만 그렇게 보자는 얘기)

다형성 Polymorphism

poly : 많은
morph : 형태

즉 다양한 형태를 가질수 있다!

같은 이름을 가진 메소드라도 조금씩 다르게 작동합니다. 이것이 바로 다형성입니다.

청사진,클래스 등등 생각하면 메소드는? 같지않나?

하지만 추상화도있고 상속도있고 등등 여러 특성적인부분을 고려하면

같은이름이지만 상속받은 부모클래스도 같지만 나자신은 다를수있는것이다.

형제끼리 같은이름의 메소드지만! 다르게 작동할수있다!!

OOP의 장점

  1. 캡슐화는 코드가 복잡하지 않게 만들고, 재사용성을 높입니다.

  2. 추상화는 마찬가지로 코드가 복잡하지 않게 만들고, 단순화된 사용으로 인해 변화에 대한 영향을 최소화합니다

  3. 상속 역시 불필요한 코드를 줄여 재사용성을 높입니다.

  4. 다형성으로 인해 동일한 메소드에 대해 if/else if와 같은 조건문 대신 객체의 특성에 맞게 달리 작성하는 것이 가능해집니다.

이후 객체 지향 프로그래밍 패러다임을 따라하면, 사람이 세계를 보고 이해하는 방법과 매우 흡사하다고 느끼게 될 것입니다.

OOP in JS : 캡슐화

캡슐화는 클로저 모듈 패턴으로도 충분히 구현된다.

오히려

class키워드를 이용한 방법은 캡슐화도 되긴하지만

JS특성상 인스턴스에 묶인 모든 속성에 직접 접근이 가능하므로 은닉화에 한계를 보인다.

(private라는게 없나 ? 따로언급이없는걸보면 없는거같기도하다..)

클로저 모듈 패턴
  
function makeCounter() {
  let value = 0
  return {
    increase: function() {
      value++ 
    },
    decrease: function() {
      value--
    },
    getValue: function() {
      return value;
    }
  }
}

let counter1 = makeCounter()
counter1.increase()
counter1.getValue() // 1

let counter2 = makeCounter()
counter2.decrease()
counter2.decrease()
counter2.getValue() // -2
  
class를 이용
  class Counter {
  constructor() {
    this.value = 0;
  }

  increase() {
    this.value++;
  }

  decrease() {
    this.value--;
  }

  getValue() {
    return this.value;
  }
}

let counter1 = new Counter()
counter1.increase()
counter1.getValue() // 1
counter1.value // 1: 접근가능

let counter2 = new Counter()
counter2.decrease()
counter2.decrease()
counter2.getValue() // -2
counter2.value // 2: 접근가능

Prototype

원형

__proto__라는것을 본적이 있을것이다.

내가 어떤 자료형을 생성할때

그 형태에 따라서

prototype에 의해서 상속받는거 같다.

그래서 __proto__의 매소드들을 사용할수있게된다.

가장 쉽게 생각하면 array에 slice라던가

string에 length같은거만 생각해도 그렇다.

어떤 자료형을 선언 할당하고

__proto__를 프로퍼티라생각하고 찍어보자.

원형이 가지고있던 속성,메소드들이 쫙 나온다.

그러므로 우리는 length, sort,slice.. 등등 편하게 js제공 메소드들을 편하게 다룰수 있는것이다.

만약 내가 객체를 만들고 거기에 __proto__에 이미존재하는 메소드이름으로
동일하게 나만의 메소드를 만든다면?

내가만든 메소드가 우선순위되며 , proto를 찾아보지 않는다(탐색을 중지한다)

이해하기 쉬운 예제


const car = {
  wheels : 4,
  drive(){
    console.log("drive..");
  },
};

const bmw = {
  color : "red",
  navigation : 1,
  //wheels : 4,
  //drive(){
  //  console.log("drive..");
  //},
};
      
const benz = {
  color : "black",
  //wheels : 4,
  //drive(){
  //  console.log("drive..");
  //},
};

const audi = {
  color : "blue",
  //wheels : 4,
  //drive(){
  //  console.log("drive..");
  //},
};

bmw.__proto__ = car;
benz.__proto__ = car;
audi.__proto__ = car;

const x5 ={
  color : "while",
  name : "x5",
};

x5.__proto__ = bmw;
// 상속은 이어질수있다.

이렇게 프로토 를 주는방법으로 상속시킬수있다.

for in 문을 사용하면 사용자가 직접 proto타입에 상속시킨 키벨류에 접근가능하고

Object.keys나 Object.values는 상속받은내용은 접근불가능하다.

for in 문에서 상속받은내용을 안보려면 hasOwnProperty라는 기본 object내부 메서드로 로 한번 걸러내면 된다.

__proto__ 말고도 생성자함수 에서도 줄수있다.

생성자함수가



const Bmw = function (color) {
  this.color = color;
};

Bmw.prototype.wheels = 4;
Bmw.prototype.drive = function(){
  console.log("drive..");
};

const x5 = new Bmw("red");
const z4 = new Bmw("blue");

인스턴스를 확인하는방법

z4 instanceof Bmw
true

생성자로 만들어진 인스턴스에는 constructor라는 프로퍼티가존재한다.
z4.constructor === Bmw;
true

하지만

Bmw.prototype.wheels = 4;
Bmw.prototype.drive = function(){
  console.log("drive..");
}; // 왜 이렇게 길게 썻지? 하나로 묶으면되지않나 ?

Bmw.prototype = {
  wheels :4,
  drive() {
    console.log("drive..");
  }
};
//만약 이렇게 한번에 쓴다면?

z4.constructor === Bmw;
false
이렇게 false가 된다.

그래서 명시적으로 constructor를 줄수도 있다.

Bmw.prototype = {
  constructor : Bmw, // 이부분
  wheels :4,
  drive() {
    console.log("drive..");
  }
};
profile
front-back / end developer / Let's be an adaptable person

0개의 댓글