본문 바로가기
프로그래밍 기초

객체 지향 프로그래밍(Object Oriented Programming)[C++, Java]

by Deeppago 2022. 1. 20.

1. 객체 지향 프로그래밍 이란?

객체 지향 프로그래밍은 컴퓨터 프로그래밍 패러다임 중 하나로, 프로그래밍에서 필요한 요소들의 핵심적이고 특징적인 공통점들을 추상화하여 특정 상태를 가진 객체를 생성하고, 그 객체들 간의 상호작용을 통해 로직을 구현하는 프로그래밍 방법이다.

 


2. 객체 지향 프로그래밍의 특징

객체 지향 프로그래밍의 특징은 기본적으로 자료 추상화, 캡슐화, 상속다형성동적 바인딩 등의 특징이 존재한다. 객체 지향 프로그래밍은 자료 추상화를 기초로 하여 상속, 다형 개념, 동적 바인딩이 시스템의 복잡성을 제어하기 위해 서로 맞물려 기능하게 된다.

 

 

2.1 자료 추상화

자료 추상화는 불필요한 정보는 숨기고 중요한 정보만을 표현함으로써 프로그램을 간단히 만드는 것이다. 자료 추상화를 통해 정의된 자료형을 추상 자료형이라고 한다. 추상 자료형은 자료형의 자료 표현과 자료형의 연산을 캡슐화한 것으로 접근 제어를 통해서 자료형의 정보를 은닉할 수 있다. 일반적으로 추상 자료형을 클래스, 추상 자료형의 인스턴스객체, 추상 자료에게 정의된 연산을 메서드(함수), 메서드의 호출을 생성자라고 한다.

  • 클래스 : 데이터의 핵심적이고 특징적인 요소를 변수와 메서드로 정의한 것
  • 객체 : 클래스에서 정의한 것을 토대로 실제 메모리에 할당된 것으로 실제 프로그램에서 사용되는 데이터

 

2.2 캡슐화

자료 추상화에서도 설명했듯이 캡슐화는 2가지 목적이 있다.

  • 접근 제어자를 통한 정보 은닉
  • 코드를 재수정 없이 재활용하는 것

객체 지향 프로그래밍에서는 캡슐화를 통해 객체가 외부에 노출하지 않아야 할 정보 또는 기능을 접근제어자를 통해 적절히 제어 권한이 있는 객체에서만 접근토록 할 수 있다. 때문에 코드 수정이 일어났을 때 책임이 있는 객체만 수정하면 되기에 유지 보수가 쉬워진다.

뿐만 아니라 관련된 기능(메서드, methods)과 특성(data fields)을 한 곳에 모으고 분류하기 때문에 객체 재활용이 원할 해진다.

객체 지향 프로그래밍에서 기능과 특성의 모음을 클래스라는 캡슐에 분류해서 넣는 것이 캡슐화라고 생각하면 된다.

간단하게 C++에서 접근 지정자를 살펴보면 아래와 같다.

  • private : 자기 클래스 내부의 메서드에서만 접근 허용
  • protected : 자기 클래스 내부 또는 상속받은 자식 클래스에서 접근 허용
  • public : 모든 접근을 허용한다.
class Car {
// Data Fields ///////////////
public: // 지금부터 선언되는 멤버변수와 함수는 모두 접근 허용.
   int  year;
   char maker[50];

protected: // 지금부터 선언되는 멤버변수와 함수는 자기 클래스와 상속 클래스에서만 접근 허용.
   int  capEngine;

private: // 지금부터 선언되는 멤버변수와 함수는 자기 클래스에서만 접근 허용.
   char ecu[20];
   char colorCode[30];

/// Methods ///////////////////////////////////
public:
   Car() {  }  // 생성자는 외부에서 접근 허용이 되어야 한다.
   ~Car() {  }  // 소멸자

   int getMkYear() { return year; }
   int getCapEngine() { return capEngine; }

protected: // 자기 클래스 내부와 상속클래스에서 접근 허용한다.
   char* getEcuType() { return ecu; }
   char* getColorCode() { return colorCode; }

// ....
};

 

2.3 상속

상속은 새로운 클래스가 기존의 클래스의 자료와 연산을 이용할 수 있게 하는 기능이다. 상속을 받는 새로운 클래스를 자식 클래스라고 하며 새로운 클래스가 상속하는 기존의 클래스를 부모 클래스라고 한다. 기존의 클래스를 상속받은 하위 클래스를 이용해 프로그램의 요구에 맞추어 클래스를 수정(정의)할 수 있고, 클래스 간의 종속 관계를 형성함으로써 객체를 조직화할 수 있다.

 

2.4 다형성

하나의 변수명, 함수명 등이 상황에 따라 다른 의미로 해석될 수 있는 것이다.

일반적으로 오버 로딩과 오버 라이딩을 의미한다.

  • 오버 라이딩 : 같은 이름의 메서드가 여러 클래스에서 다른 기능을 하는 것
  • 오버 로딩 : 같은 이름의 메서드가 인자의 개수나 자료형에 따라서 다른 기능을 하는 것

 

2.5 동적 바인딩

동적 바인딩은 실행 시간 중에 일어나거나 실행 과정에서 변경될 수 있는 바인딩으로 컴파일 시간에 완료되어 변화하지 않는 정적 바인딩과 대비되는 개념이다. 동적 바인딩은 프로그램의 한 개체나 기호를 실행 과정에 여러 속성이나 연산에 바인딩함으로써 다형 개념을 실현한다. 

바인딩이란 프로그램 구성 요소의 성격을 결정해주는 것이다. 가령 변수의 데이터 타입이 무엇인지 정해지는 것을 예로 들 수 있다.

정적 바인딩과 동적 바인딩을 비교해 보자면 아래 표와 같다.

종류 정적 바인딩(Static binding) 동적 바인딩(Dynamic binding)
정의 컴파일 시간에 성격이 결정되는 것 실행 시간(runtime)에 성격이 결정되는 것
예시 C언어 컴파일 시간에 변수의 데이터 타입이 결정 Python(Interpreter 언어) 런타임에 값에 따라 변수의 데이터 타입이 결정
장단점 컴파일 시간에 많은 정보가 경정되므로 실행 효율 증가 런타임에 자유롭게 성격이 바뀌므로 적응성 증가

메서드의 바인딩

메서드를 만들어 컴파일을 하면 각각의 코드가 메모리 어딘가에 저장된다.

그리고 메서드를 호출하는 부분에서는 그 함수가 저장된 메모리 번지수(주소값)이 저장된다.

 

프로그램 실행 → 메서드 호출 → 메서드가 저장된 주소로 점프 → 메서드 실행 → 원래 위치

위 과정에서 메서드를 호출하는 부분에 메서드가 위치한 메모리 번지로 연결시켜 주는 것을 바인딩(Binding)이라고 한다.

 

-메서드를 바인딩 하는 2가지 방법

  • 정적 바인딩 (일반 메서드)
    • 컴파일 시간에 호출될 메서드로 점프할 주소가 결정되어 바인딩되는 것
  • 동적 바인딩 (가상 메서드)
    • 실행 파일을 만들 때 바인딩 되지 않고 보류 상태로 둔다.
    • 점프할 메모리 번지를 저장하기 위한 메모리 공간을 가지고 있다가 런타임에 결정.
    • 타입 체킹으로 인한 수행 속도가 저하된다는 단점이 있다.

동적 바인딩을 하는 이유

어떤 포인터에 의해접근되었는 지에 상관없이 참조된 인스턴스의 실제 클래스형에 따라 재정의된 함수 호출이 가능(다형성)

 


3. 객체 지향 프로그래밍의 장단점

객체 지향 프로그래밍의 정의와 특징을 알아보았으니 장단점에 대해서도 알아보자.

 

3.1 장점

  • 재사용성 : 상속을 통해 프로그래밍 시 코드의 재사용을 높일 수 있다.
  • 생산성 향상 : 잘 설계된 클래스를 만들어서 독립적인 객체를 사용함으로써 개발의 생산성을 향상시킬 수 있다.
  • 유지보수의 우수성 : 프로그램 수정 시 추가, 수정을 하더라도 캡슐화를 통해 주변 영향이 적기 때문에 유지보수가 쉬워서 매우 경제적이다.

3.2 단점

  • 개발 속도가 느리다 : 객체가 처리하려는 것에 대한 정확한 이해가 필요하기에 설계단계부터 많은 시간이 소모된다.
  • 실행 속도가 느리다 : 객체지향 언어는 대체적으로 실행 속도가 느리다.
  • 코딩 난이도 상승 : 다중 상속이 지원되는 C++ 같은 경우에 너무 복잡해져 코딩의 난이도가 상승할 수 있다.

 


4. Getter와 Setter 메서드

객체 지향 프로그래밍에서 객체의 데이터는 객체 외부에서 직접적으로 접근하는 것을 막는다.

객체 데이터를 외부에서 일고 변경 시 객체의 무결성이 깨질 수 있기 때문이다. 예를 들어 자동차의 속도는 음수를 가질 수 없다. 하지만 외부에서 음수로 설정하면 객체의 무결성이 깨진다. 따라서 객체 지향 프로그래밍에서는 메서드를 통해 데이터를 변경하는 방법을 선호한다.

객체 지향 프로그래밍에서는 캡슐화를 위해 prevate을 사용하는 멤버 변수는 외부에서 접근하지 못하기 때문에 Getter와 Setter메서드를 클래스 내부에 public으로 선언하여 멤버 변수에 접근하게 된다. 데이터를 외부에서 접근하지 못하도록 막고, 메서드는 공개하는 것이라 이해하면 된다.

 

4.1 Setter 메서드

외부에서 메서드를 통해 데이터에 접근하도록 하는 것이 Setter 메서드이다. 아래 자바 코드를 보자.

자동차의 속도를 setSpeed() 메서드로 변경할 경우 아래와 같이 음수 속도에 대해서 처리할 수 있다.

public void setSpeed(double speed) {
	if(speed < 0) {
		this.speed = 0;
		return;
	} 
	else {
		this.speed = speed;
	}
}

 

4.2 Getter 메서드

외부에서 메서드를 통해 객체의 데이터를 읽을 때 Getter 메서드를 사용한다. 아래 자바 코드를 보자.

객체 외부에서 객체 필드 값을 사용하기 부적절한 경우가 있다. 이런 경우 메서드로 필드 값을 가공 후, 외부로 전달한다.

public double getSpeed(){
	double km = speed * 1.6;
	return km;
}

 


마치며

기본기가 부족한 것 같아 초심으로 돌아가 기초적인 프로그래밍에 대한 지식부터 정리하려고 한다.

주로 Python을 많이 사용하여 C++이나 java를 많이 잊어버려서 다시 상기시킬 겸 예시를 C++과 java로 들어보았다.

부족하지만 이 글이 누군가에게 도움이 되었으면 한다.

바인딩의 개념에 대해서는 따로 글을 적어 정리해 보도록 하겠다.

댓글