이전 포스트에서, 캡슐화와 관련된 내용을 정리하며 객체지향 프로그래밍(Object Oriented Programming, OOP)의 4가지 특징을 잠깐 언급했었다.
이번 포스트에서는 객체, 그리고 객체 지향 프로그래밍이 무엇인지에 대해 정리한다.
객체란 물리적, 혹은 추상적으로 존재하는 것 중 자신의 속성과 기능을 가지고 다른 것과 구분이 가능한 모든 것을 의미한다.
또한 컴퓨터 공학에서의 객체란 변수, 자료 구조, 함수, 메서드, 식별자에 의해 참조된 메모리 상의 값이란 의미를 가지며 프로그래밍적 관점에서는 구현해야 할 대상이자 속성과 기능을 가지는 프로그램의 단위라 할 수 있다.
이 객체라는 개념과 자주 혼용되는 용어가 클래스와 인스턴스다.
클래스는 흔히, 객체를 생성하기 위한 설계도로 많이 비유된다.
클래스는 필드(Field)와 메소드(Method)를 가진다. 필드는 객체의 속성을 정의하고 메소드는 객체의 기능을 정의한다. 이것들은 생략될 수도, 하나 이상을 가질 수도 있다.
설계도에 해당하는 클래스만으로는 객체를 사용할 수 없다. 객체를 사용하기 위해서는 클래스를 사용하여 새로운 인스턴스를 생성해야만 사용할 수 있다.
클래스의 정보는 JVM 메모리의 클래스 영역(Class Area)에 저장된다.
인스턴스는 클래스를 바탕으로 메모리 상에 할당된 실체이다.
객체와 유사하지만 구현된 실체인 인스턴스는 구현해야 할 대상인 객체에 포함된다고 볼 수 있다.
(static한 요소를 제외하고) 객체를 사용하기 위해서는 반드시 인스턴스를 생성해야 하며 클래스명을 참조타입으로 가지는 변수에 참조되어야 한다. 참조되지 않은 인스턴스는 사용할 수 없다.
인스턴스를 생성하는 방법은 아래의 3가지가 있으며 일반적으로는 new연산자와 생성자를 이용하는 방법을 주로 사용한다.
ClassName VariableName = new ClassName();
생성된 인스턴스는 힙 영역(Heap Area)에 저장된다.
객체지향 프로그래밍(Object Oriented Programming, OOP)이란 개념의 자연스러운 이해를 위해 객체지향 프로그래밍이 등장하기 이전의 프로그래밍 패러다임에 대해 간략하게 알아볼 필요가 있다.
비구조적 프로그래밍이라고도 하는 이 방식은 코드의 흐름과 순서에 기반하여 동작을 추가하며 프로그램을 완성하는 방식이다.
흐름이 보이기 때문에 직관적이라는 장점이 있으나 프로그램이 복잡해질수록 코드의 중복이 발생하고 코드 자체가 어지러워지는 문제가 발생한다.
이러한 문제를 해결하기 위해 코드를 단위화할 방법을 고안하고, 이로인해 '절차적 프로그래밍'이 등장한다.
구조적 프로그래밍이라고도 하는 이 방식은 반복되는 동작을 재사용 가능한 프로시저(리턴값이 없는 함수) 형태로 모듈화하여 사용하는 방식이다.
절차적 프로그래밍의 도입으로 반복 동작을 모듈화하여 무분별하게 중복되던 코드를 많이 줄일 수 있었으나 프로시저라는 추상적인 단위로는 물리적인 요소(변수나 상수등의 값)를 관리하기 어렵다는 문제가 새롭게 대두되었다.
위의 문제를 해결하기 위해 '객체지향 프로그래밍'이라는 새로운 패러다임이 등장한다.
객체지향 프로그래밍은 설계에서 가능한 모든 물리적, 논리적 요소들을 객체 단위로 나누어 만든다.
이렇게 나뉜 객체는 내부에 자료형(Field)과 함수(Method)를 함께 가지며 다른 객체로부터 높은 독립성을 가진다.
최종적으로 객체지향 프로그래밍은 만들어진 각각의 객체를 조립하여 하나의 프로그램을 만드는 것을 의미한다.
객체지향 프로그래밍에는 추상화(Abstraction), 캡슐화(Encapsulation), 상속(Inheritance), 다형성(Polymorphism)의 4가지 원칙이 있다.
코드 재사용 용이
모듈화된 객체, 그리고 상속을 통해 코드의 재사용을 높일 수 있다.
생산성 향상
독립적인 객체를 사용함으로써 개발의 생산성을 향상시킬 수 있다. (상속, 객체의 재사용, 오버라이딩 등)
유지보수 용이
객체 간의 높은 독립성을 보장받기에 유지보수에 용이하다.