객체 지향 프로그맹에 대한 내용입니다.
객체 지향 프로그래밍( OOP: Object-Oriented-Programming )은 컴퓨터 프로그램을 어떤 데이터를 입력받아 순서대로 처리하고 결과를 도출하는 명령어들의 목록으로 보는 시각에서 벗어나 여러 독립적인 부품들의 조합, 즉 객체들의 유기적인 협력과 결합으로 파악하고자 하는 컴퓨터 프로그래밍의 패러다임을 의미합니다.
객체 지향 프로그래밍의 장점
먼저 가장 큰 이점 중에 하나는 객체 지향적 설계를 통해 프로그램을 보다 유연하고 변깅이 용이하게 만들 수 있다는 점입니다. 소프트웨어를 설계할 때 객체 지향적 원리를 잘 적용해 둔 프로그램은 각각의 부품들이 각자의 독립적인 역할을 갖기 때문에 코드의 변경을 최소화하고 유지보수를 하는데 유리합니다.
좀 더 나아가, 코드의 재사용을 통해 반복적인 코드를 최소화하고, 코드를 간결하게 표현할 수 있습니다.
객체 지향 프로그래밍의 4가지 특징
객체 지향 프로그래밍은 소프트웨어 시스템을 설계하고 구현하기 위해 추상화, 상속, 다형성, 캡슐화의 개념이 존재합니다.
1. 추상화
- 추상화는 불필요한 세부 사항을 숨기고 객체의 본질적인 특성을 기반으로 클래스를 모델링하여 복잡한 현실을 단순화하는 프로세스입니다.
- 개체가 어떻게 수행하는지보다는 개체가 수행하는 작업에 중점을 두어 복잡한 시스템 작업을 더 쉽게 만들어줍니다.
2. 상속
- 상속을 사용하면 클래스가 다른 클래스에서 속성과 메서드를 상속할 수 있습니다. 이는 코들 재사용성을 촉진하고 기존 클래스의 기능을 확장하는 특수 클래스 생성을 촉진합니다.
3. 다형성
- 다형성을 통해 서로 다른 클래스의 객체를 공통 슈퍼클래스의 객체로 처리할 수 있습니다. 이를 통해 동적 메서드 호출 및 메서드 재정의가 가능해지며, 특정 구현에 따라 서로 다른 객체가 동일한 메서드 호출에 다르게 응답할 수 있습니다.
4. 캡슐화
- 캡슐화는 데이터( 속성 )와 해당 데이터에 대해 작동하는 메서드( 함수 )를 클래스라는 단일 단위로 묶는 개념입니다.
- 객체의 내부 상태에 대한 액세스를 제한하여 잘 정의된 인터페이스( 공용 메서드 )를 통해 제어된 액세스를 허용합니다.
예제로 보는 객체 지향 프로그래밍
item이라는 반복되는 객체가 존재할 때의 예입니다.
let name = "Jun Store";
let item = {
name: "삼성TV",
price: 100,
size: "24inch"
}
let item2 = {
name: "LG TV",
price: 500,
size: "56inch"
}
위처럼 item이라는 객체를 반복적으로 생성할 때 사람은 실수를 할 수 있습니다. 예를들어 name을 빼먹는다던지, price를 빼먹는 다던지.
이런 실수를 막기위한 것이 class입니다.
class는 어떤 속성과 기능이 있는지 정의해둔 지시서입니다. 아래처럼 표현할 수 있습니다.
// 클래스
class Items {
name = "";
price = 0;
size = "";
// 생성자 ( Items를 생성할 때는 name, price, size가 꼭 포함되어야 한다. )
constructor(name, price, size) {
this.name = name,
this.price = price,
this.size = size
}
};
- constructor: 클래스에 있는 속성들에 값을 초기화 시켜주는 함수 생성자입니다.
- this: this를 사용해서 구분 지을 수 있습니다 ( ex: this.name은 class내부의 name이다 라는것을 알려줌. )
class를 가지고 item을 생성하기
let item = new Items("삼성TV", 100, "24inch");
let item2 = new Items("LG TV", 500, "56inch");
console.log(item);
console.log(item2);
/*
Items { name: '삼성TV', price: 100, size: '24inch' }
Items { name: 'LG TV', price: 500, size: '56inch' }
*/
class 상속( extends )
// 추상화
class Product {
name = "";
price = 0;
constructor(name, price) {
this.name = name,
this.price = price
}
}
// 상속
class Items extends Product {
size = "";
constructor(name, price, size) {
// super()는 내 상위 클래스를 부를 때 사용합니다.
super(name, price),
this.size = size
}
};
class Phone extends Product {
size = "";
type = "";
}
class Computer extends Product {
model = "";
status = "";
}
extends를 사용하게되면 Product의 내용을 가져와서 사용할 수 있도록 확장시켜줍니다.
위처럼 사용하게 되면 항상 겹치는 내용인 name과 price를 extends 시켜서 매번 클래스를 생성할 때 추가 시키지 않아도 됩니다.
이런 작업이 필요한 이유는 Computer를 판매할 때 상품번호, 제조사, 브랜드, 원산지, 종류, CPU종류, 속도 등등 여러가지 내용을 추가 시켜 주어야 하는데 이렇게 공통된 부분을 빼주게 된다면 간략화 시킬 수 있습니다.
이후에 공통된 정보가 추가 되었을 때 Product에만 추가를 시켜주면 extends된 부분에서 사용할 수 있게 됩니다.
Items에서 사용하던 this.name과 this.price는 상위 클래스로 넘어갔기 때문에 this를 사용할 수 없게 됩니다. 그래서 상위 클래스를 부를 수 있는 super()를 사용해서 상위 클래스에서 name과 price를 불러와줍니다.
class에 함수 추가하기
class Product {
name = "";
price = 0;
constructor(name, price) {
this.name = name,
this.price = price
};
getPrice() {
return this.price + "만원";
};
}; // 캡슐화
let item = new Items("삼성TV", 100, "24inch");
console.log(item.getPrice()); // 100만원
위처럼 삼성TV의 가격이 100인 경우 원인지 만원인지 알 수 없기 때문에 함수를 사용해서 바꿔줄 수 있습니다.
이렇게 변수들과 변수에 관련된 함수들을 같은 클래스에 정의를 해서 패키지처럼 사용할 수 있는 것을 캡슐화라고 합니다.
class에 악의적인 내용 방지하기
위 같은 내용으로 결과값을 받으면 문제점이 있습니다.
item.price = -500;
console.log(item.getPrice());
위처럼 중간에 개발자가 실수로 -를 넣게되면 위처럼 -500만원이라는 금액이 표기됩니다.
이런것을 방지하기 위해 아래처럼 사용할 수 있습니다.
class Product {
name = "";
price = 0;
constructor(name, price) {
this.name = name,
this.price = price
};
getPrice(price) {
if (price < 0) return console.log("Minus Err!!!");
return this.price = price + "만원";
}
}
let item = new Items("삼성TV", 100, "24inch");
console.log(item.getPrice(500)); // 500만원
console.log(item.getPrice(-500)); // Minus Err!!!
이렇게 표현을 해주면 중간에 실수를 해도 바로바로 확인이 가능해집니다.