[TIL] 200909 객체지향프로그래밍(Object Oriented Programming, OOP)

Chaegyeom·2020년 9월 9일
0

TIL

목록 보기
30/77
post-thumbnail

객체지향프로그래밍(Object Oriented Programming, OOP)이란?

프로그램 설계방법론이자 개념의 일종.

프로그램을 단순히 데이터와 처리 방법으로 나누는 것이 아니라, 프로그램을 수많은 '객체'라는 기본 단위로 나누고 이 객체들의 상호작용으로 서술하는 방식

출처 : wiki

객체지향 언어

프로그램이 객체(object)의 집합으로 구성될 수 있도록 구성된 언어이다.

객체지향 프로그래밍

이전의 패러다임이던 프로그래밍(Sequential Programming), 절차적 프로그래밍(Procedural Programming)등을 두고 왜 객체지향 프로그래밍(Object Oriented Programming)의 패러다임으로 바뀌게 되었을까?

절차적 프로그래밍(Procedural Programming)의 procedural(function)단위의 아쉬운 점을 채우기 위해서 객체지향 프로그래밍(Object Oriented Programming)이 고안되고 도입되게 되었다.
예를 들면 물품들을 정리하는 프로그램을 짠다고 생각해보면 기존의 절차적프로그래밍의 패러다임에서는 물품들에 대한 데이터가 필요하고 또 그 데이터들을 정리하는 함수가 필요하다. 그런데 코드가 짧다면 문제가 없지만 점점 길어진다면 알기가 힘들어질 것이다.

객체지향 프로그래밍(Object Oriented Programming)이란 이런 데이터와 함수를 묶기 위한 패러다임이다. 프로그램을 실제 세상에 가깝게 모델링하기 위한 방법이다. 컴퓨터가 수행하는 작업을 객체들간의 상호작용으로 표현하고 클래스 혹은 객체들의 집합으로 프로그램을 작성한다.

객체지향 프로그램은 가능한 모든 물리적, 논리적 요소들을 객체로 만들기 위해 노력하는데, 이는 코딩을 시작한 초반에는 조금 불편하나 시간이 지날수록 중복코딩이 줄게되고 객체들간의 독립성이 있기 때문에 유지보수에 도움이 된다.

객체지향프로그래밍의 초창기에는 변수와 함수를 묶는 선에서만 프로그래밍이 이루어졌으나 점차 그 독립성을 지키키 위해 발전되어 왔다. 그래서 여러 특성이 생기게 되었는데 아래와 같다

캡슐화(encapsulation)

객체의 데이터(Data fields)와 함수(methods)를 하나의 클래스 라는 캡슐에 묶는 것
함수와 데이터를 클래스 내에 선언하고 구현한다.

외부에서는 공개된 메소드의 인터페이스만 접근 가능하고 객체 내의 데이터에 대한 외부의 접근을 제한하기 때문에 정보를 은닉할 수 있다. 따라서 외부요소에 의한 문제를 줄일 수 있다.

상속(Inheritance)

상위클래스(superclass)의 속성(변수)와 기능(메소드,함수)을 하위클래스(subclass)가 물려받는 것

하위클래스(subclass)는 상위클래스(superclass)의 기능을 새로 정의하지 않고 사용할 수 있기 때문에 코드의 중복을 줄일 수 있고, 상위클래스에서 코드를 공통적으로 관리할 수 있기 때문에 유지보수에 용이하다. 또한, 하위클래스에서 필요한 기능을 추가할 수 있기에 확장성 또한 높다고 할 수 있다.

다형성(Polymorphism)

하나의 클래스 내부에 같은 이름의 행위를 파라미터의 개수를 다르게 하여 여러개 정의하거나, 상위 클래스의 메소드를 재정의하여 사용할 수 있는 것

하나의 타입을 여러 개의 객체로 해석하는 개념으로 다형성 개념을 사용하는 방법으로는 오버라이딩오버로딩이 있다.

  • 오버라이딩(Overriding)
    하위클래스(subclass)는 상위클래스(superclass)와 같은 이름, 인자, 반환 값을 가지게 되는데 이것을 자식객체에서 재정의하는 것을 오버라이딩이라고 한다.
  • 오버로딩(Overloading)
    하나의 클래스에서 같은 이름의 메소드들을 여러 개 가지고 있는 것, 같은 이름에 다른 기능일 때 사용하며 컴파일러의 구분을 위해서 인자의 종류, 숫자를 다르게 정의해야 한다.

추상화(Abstraction)

객체지향에서의 추상화는 모델링이다. 디테일한 것보다는 필요성에 의해 있어야할 정보들만 간추려서 구성하는것
어느정도 틀만 갖춰놓은 추상클래스를 상속받은 하위클래스에서 완성되게 하는것이다.

Javascript에서 Object를 생성하는 방법

1. Functional

Car라는 함수를 만들고 함수가 실행될 때 찍어내줄 객체를 함수안에 선언한다

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

먼저 Car함수를 선언한다. position을 바로 someInstance의 property로 넣어준 것 외에는 다른 부분은 없다.

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

메소드를 담아줄 객체를 생선한다. 모든 메소드는 someMethods에 담는다

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

그 후 someInstance와 someMethods를 합치는 extend함수를 만들어서 Car함수 내부에서 합쳐준다

let extend = function(to, from) {
	for(let 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, someMethods)
	return someInstance;
};
let car1 = Car(5);
let car2 = Car(10);

왜 이렇게 번거로운 방식을 사용할까?
functional방식은 인스턴스를 생성할 때 마다 모든 메소드를 someInstance에게 할당하므로, 각각의 인스턴스들이 메소드의 수만큼의 메모리를 더 차지한다. 하지만 functional shared방식은 someMethods라는 객체에 있는 메소드들의 메모리 주소만을 참조하기 때문에 메모리 효율이 좋아진다.

3. Prototypal

우선 Functional Shared 방식과 비슷하게 코드를 작성한다.

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

let someInstance = {};부분만 변경한다.

let someMethods = {};
	someMethods.move = function() {
		this.position += 1;
	};
let Car = function(position) {
	let someInstance **= Object.created(someMethods);**
	someInstance.position = position;
	return someIntance
};
let car1 = Car(5)
let car2 = Car(10);
  • Object.create의 역할 : 특정 객체를 프로토타입으로 하는 객체를 생성해 주는 함수이다.

4. Pseudoclassical

프로토타입을 만들고 변수를 선언할때 new operator을 붙이는게 특징이다

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

메소드를 프로토타입으로 만들어준다.

let Car = function(position) {
	this.position = position
};
**Car.prototype.move = function() {
	this.position +=1;
};
//찍어낼 때 new operator를 붙여야 한다
let car1 = new Car(5);
let car2 = new Car(10);**

Javascript에서 prototype

프로토타입 기반 프로그래밍은 객체지향 프로그래밍의 한 형태로 클래스가 없고, 클래스 기반 언어에서 상속을 사용하는 것과는 다르게, 객체를 원형(프로토타입)으로 하여 복제의 과정을 통하여 객체의 동작 방식을 다시 사용할 수 있다.

프로토타입기반 프로그래밍은 클래스리스(class-less), 프로토타입 지향(prototype-oriented) 혹은 인스턴스 기반(instance-based) 프로그래밍이라고도 한다.
출처 : wiki

자바스크립트의 모든 객체는 자신을 생성한 객체 원형에 대한 숨겨진 연결을 갖는다. 이때 자기 자신을 생성하기 위해 사용된 객체원형을 프로토타입이란 한다. 자바스크립트의 모든 객체는 Object 객체의 프로토타입을 기반으로 확장 되었기때문에 이 연결의 끝은 Object 객체의 프로토타입 Object다.

그럼 프로토타입을 왜 사용해야 할까?
생성자 함수에서 new키워드를 통해서 객체를 생성해보자

function Human() {
  this.hand = 2;
  this.nose = 1;
}
var hae  = new Human();
var bae = new Human();
console.log(hae.hand);  // => 2
console.log(hae.nose);  // => 1
console.log(bae.hand); // => 2
console.log(bae.nose); // => 1

그렇다면 프로토타입을 통해 객체를 생성해보자

function Human() {}

Human.prototype.hand = 2;
Human.prototype.nose = 1;

var hae  = new Human();
var bae = new Human();
console.log(hae.hand);  // => 2
console.log(hae.nose);  // => 1
console.log(bae.hand); // => 2
console.log(bae.nose); // => 1

생성자 함수랑 프로토타입의 결과는 같은데 어떤 차이가 있다는 걸까?
생성자 함수에서는 hae,bae둘다 hand와 nose를 가지고 있는데 메모리에서는 hand와 nose가 두개씩 총 4개가 할당된다.
하지만 프로토타입에서는 Human이라는 Object에서 hae와 bae가 공유해서 사용하는 것이다.

따라서 메모리의 효율성 측면에서 프로토타입을 사용하게 된다.

profile
주니어 개발자가 되고싶은

0개의 댓글