CS 공부) 객체 지향 프로그래밍이란 무엇인가
Object Oriented Programming (객체 지향 프로그래밍)
객체 지향 프로그래밍 이전의 프로그래밍 패러다임을 살펴보면, 중심이 컴퓨터에 있었다. 컴퓨터가 사고하는대로 프로그래밍을 하는 것이다. 하지만 객체지향 프로그래밍이란 인간 중심적 프로그래밍 패러다임이라고 할 수 있다. 즉, 현실 세계를 프로그래밍으로 옮겨와 프로그래밍하는 것을 말한다. 현실 세계의 사물들을 객체라고 보고 그 객체로부터 개발하고자 하는 애플리케이션에 필요한 특징들을 뽑아와 프로그래밍 하는 것이다. 이것을 추상화라한다.
OOP 로 코드를 작성하면 이미 작성한 코드에 대한 재사용성이 높다. 자주 사용되는 로직을 라이브러리로 만들어두면 계속해서 사용할 수 있으며 그 신뢰성을 확보 할 수 있다. 또한 라이브러리를 각종 예외상황에 맞게 잘 만들어두면 개발자가 사소한 실수를 하더라도 그 에러를 컴파일 단계에서 잡아낼 수 있으므로 버그 발생이 줄어든다. 또한 내부적으로 어떻게 동작하는지 몰라도 개발자는 라이브러리가 제공하는 기능들을 사용할 수 있기 때문에 생산성이 높아지게 된다. 객체 단위로 코드가 나눠져 작성되기 때문에 디버깅이 쉽고 유지보수에 용이하다. 또한 데이터 모델링을 할 때 객체와 매핑하는 것이 수월하기 때문에 요구사항을 보다 명확하게 파악하여 프로그래밍 할 수 있다.
객체 간의 정보 교환이 모두 메시지 교환을 통해 일어나므로 실행 시스템에 많은 overhead 가 발생하게 된다. 하지만 이것은 하드웨어의 발전으로 많은 부분 보완되었다. 객체 지향 프로그래밍의 치명적인 단점은 함수형 프로그래밍 패러다임의 등장 배경을 통해서 알 수 있다. 바로 객체가 상태를 갖는다는 것이다. 변수가 존재하고 이 변수를 통해 객체가 예측할 수 없는 상태를 갖게 되어 애플리케이션 내부에서 버그를 발생시킨다는 것이다. 이러한 이유로 함수형 패러다임이 주목받고 있다.
객체지향의 4가지 특징을 정리해보았다.
1. 추상화(Abstraction)
프로그램을 만듬에 있어서 간단한 예를 생각하려 한다.
스타크래프트에서 유닛을 만든다고 생각을 한다.
그러면 기본적으로 들어갈 정보들을 생각 할 수있을 것이다. 그리고 구체화 시켜 나가는 것이다.
예를 들어 HP, MP, NAME 과 같은 데이터들과 이동, 공격 과 같은 함수들이 존재 할 것이다.
이러한 추상화를 통해서 Class를 만들어 놓고 저글링이나 질럿 마린과 같은 상세한 부분들을 채워 나가는 것이다.
//가상 클래스
//기본적인 몬스터들의 틀[Class]
//추상 클래스
class Unit{
//태어나는 위치
private :
int x;
int y;
//기본 속성
protected:
unsigned char HP;
unsigned char MP;
char name[20];
//생성자
//태어남
//소리남 응애응애
public:
Unit();
virtual void born() = 0;
virtual void sound() = 0;
};
2. 캡슐화(Encapsulation)
객체의 내용 중 숨기고 싶은 부분은 외부에서 접근 할 수 없다.
단지 해당 객체내의 함수에 의해서만 접근 가능 하도록 하는 것이다. 이를 통해서 정보 은닉이 가능해진다.
앞서 말한 접근제어[public, private, protected]와 같은 내용에 의해서 구현 되어진다.
접근 권한을 통해 제공되며 원하지 않는[실수] 외부의 접근에 대해 내부의 데이터, 함수를 보호하는 작용
이렇게 함으로써 이들 부분이 프로그램의 다른 부분들에 영향을 제한.
예를 들어 설명하면, 각 Unit마다 고유한 값이 존재한다.
하지만 같은 변수명을 사용함에 있어서 실수로 고유한 값을 수정 해버리면 문제가 발생 한다.
이러한 문제를 해결 해준다.
//유닛에서 저글링 만들기 class zergling : public Unit{ //speed 추가 private: unsigned char speed; public: zergling(); virtual void move(); virtual void sound(); void up_speed(); void up_speed(int var); };
//priveate 영역 접근 가능한 클래스 내 함수 void zergling::up_speed(){ speed += 10; }
3. 상속(Inheritance)
Class의 멤버[데이터]와 함수를 다른 Class에 물려주거나, 물려 받는 것을 말한다.
이를 통해서
1.코드의 재사용을 증대 시킬 수있다. 같은 기능을 또 구현 할 필요가 없다.
2. 좀 더 폭넓게 사용 가능하다. 상속 받은 함수를 추가적으로 데이터와 함수 내용을 변경 가능.
같은 기능을 가진 함수는 그대로 사용 할수있고, 같은 기능의 함수를 다른 이름으로 만들 필요도 없어진다.
내 생각이지만 이를 통해서 다형성도 확보되는것 같다.
//유닛에서 저글링 만들기 class zergling : public Unit{ //speed 추가 private: unsigned char speed; public: zergling(); virtual void move(); virtual void sound(); void up_speed(); void up_speed(int var); }; //Unit을 상속 받아서 zergling 생성
4. 다형성(Polymorphism)
다양한 형태로 표현이 가능하다는 의미이다.
예를 들어 설명하면 사람의 말투와 같은 느낌인것 같다.
사람의 말투에 따라서 야. 야!, 야~ 와 같이 다른 의미를 전달한다.
야. 는 정색하는 말투.
야!는 호통 하는 말투
야~ 는 애교를 부리는 말투
등으로 같은 [야] 이지만 다른 의미를 전달하는 느낌이다.
여기서는 Overloading과 Overriding으로 표현이 가능하다.
두개의 의미는 알지만 항상 햇갈렸는데 단어 뜻을 알아보고 간다.
Overload는 초과 적재라는 의미, Overriding 무효화 하다 라는 의미이다.
Overload는 하나의 함수에 여러개의 기능을 부여하는것.
Override는 기존의 기능을 고려 하지 않고 새로운 기능을 부여하는 것.
Dynamic Binding이라는 개념도 해당 다형성에서 나온다.
함수가 호출 되기 전까지는 up_speed()함수 중 어떠한 것과 연결 되는지 모른다.
하지만 up_speed()가 호출 되면 속도가 +10이 되고, up_speed(30)하면 +30으로 연결 될 것이다.
이러한 내용을 동적 바인딩이라고 한다.
1. 오버로딩[Overloading]
같은 기능의 함수에 같은 이름을 사용 할수있어서 가독성 증가
하나의 함수에 여러 메개변수 가능
조건:
함수명은 동일 해야함.
넘겨주는 인자[메개변수]는 달라야 함.
리턴 타입은 상관 없음.
2. 오버라이딩[Overriding]
상속으로 받은 함수를 그대로 사용하지 않고 새로 만들어서 사용.
코드의 재사용성을 역시 증가 시킨다.
조건:
함수명은 동일 해야함.
넘겨주는 인자 같아야 함.
리턴 타입 같아야함.
void zergling::up_speed(){
speed += 10;
}
void zergling::up_speed(int var){
speed += var;
}
//오버로딩[Overloading]
void zergling::sound(){
printf("북적 북적\n");
}
void Unit::sound(){
printf("꿈틀 꿈틀.. 아무런 소리가 나지 않는다.\n");
}
// 오버라이딩
[참고]
객체 지향적 설계 원칙
- SRP(Single Responsibility Principle) : 단일 책임 원칙
클래스는 단 하나의 책임을 가져야 하며 클래스를 변경하는 이유는 단 하나의 이유이어야 한다. - OCP(Open-Closed Principle) : 개방-폐쇄 원칙
확장에는 열려 있어야 하고 변경에는 닫혀 있어야 한다. - LSP(Liskov Substitution Principle) : 리스코프 치환 원칙
상위 타입의 객체를 하위 타입의 객체로 치환해도 상위 타입을 사용하는 프로그램은 정상적으로 동작해야 한다. - ISP(Interface Segregation Principle) : 인터페이스 분리 원칙
인터페이스는 그 인터페이스를 사용하는 클라이언트를 기준으로 분리해야 한다. - DIP(Dependency Inversion Principle) : 의존 역전 원칙고수준 모듈은 저수준 모듈의 구현에 의존해서는 안된다.