- 객체지향 프로그래밍은 컴퓨터 프로그래밍 패러다임(견해, 사고법)의 하나로, 프로그래밍에서 필요한 데이터를 추상화 시켜서 상태(속성, 어트리뷰트)와 행위(메서드)를 가진 객체로 만들고, 그 객체간의 상호작용을 통해 로직을 구성하는 방법입니다.
- 객체지향 애플리케이션의 중심 사상은 연쇄적으로 메시지를 전송하고 수신하는 객체들 사이의 협력 관계를 기반으로 사용자에게 유용한 기능을 제공하는 것입니다. 객체지향의 강력함은 객체들이 주고받는 메시지로부터 나옵니다. 객체지향의 애플리케이션은 클래스를 이용해 만들어지지만 메시지를 통해 정의됩니다.
- 객체 지향 프로그래밍은 제어흐름의 간접적인 전환에 부과되는 규율입니다.
자율적인 책임
- 객체지향 공동체를 구성하는 기본 단위는
자율적인 객체
입니다. - 자율적인 객체란 스스로 정한 원칙에 따라 판단하고 스스로의 의지를 기반으로 행동하는 객체입니다. 객체가 어떤 행동을 하는 유일한 이유는 다른 객체로부터 요청을 수신했기 때문입니다.
요청을 처리하기 위해 객체가 수행하는 행동
을 책임이라고 합니다. - 적절한 책임이 자율적인 객체를 낳고, 자율적인 객체들이 모여 유연하고 단순한 협력을 낳습니다. 따라서
협력에 참여하는 객체가 얼마나 자율적인지가 전체 어플리케이션의 품질을 결정합니다
. 객체가 책임을 자율적으로 수행하기 위해서는 객체에게 할당되는 책임이 자율적이어야 합니다. 책임이 자율적이지 않다면 객체가 아무리 발버둥친다고 하더라도 자율적으로 책임을 수행하기 어렵습니다. - 자율적인 책임의 특징은 객체가 어떻게해야 하는가가 아니라
무엇을 해야하는가
를 설명한다는 것입니다. 책임이라는 말 속에는 어떤 행동을 수행한다는 의미가 포함돼 있습니다. 객체지향 공동체 안에 거주하는 객체는 다른 객체로부터 전송된 요청을 수신할 때만 어떤 행동을 시작합니다. - 사실 객체가 다른 객체에게 접근할 수 있는 유일한 방법은 요청을 전송하는 것뿐입니다. 그리고 이 요청을 우리는 메시지라고 부릅니다. 메시지는 객체로 하여금 자신의 책임, 즉 행동을 수행하게 만드는 유일한 방법입니다.
- 성급한 일반화의 오류를 피하고 현재의 문맥에 가장 적합한 책임을 선택할 수 있는 날카로운 안목이 필요합니다.
메시지와 메서드
- 하나의 객체는 메시지를 전송함으로써 다른 객체에 접근합니다.
- 객체의 행동을 유발하는 행위를 가리켜 메시지-전송이라고 합니다.
- 메시지-전송 메커니즘은 객체가 다른 객체에 접근할 수 있는 유일한 방법입니다.
- 객체가 제공하는 메시지는 외부의 다른 객체가 볼 수 있는 공개된 영역에 속합니다. 메시지를 처리하기 위해 책임을 수행하는 방법은 외부의 다른 객체가 볼 수 없는 객체 자신의 사적인 영역에 속합니다. 객체가 유일하게 이해할 수 있는 의사소통 수단은 메시지뿐이며 객체는 메시지를 처리하기 위한 방법을 자율적으로 선택할 수 있습니다.
- 메시지가 ‘어떻게’ 수행될 것인지는 명시하지 않습니다. 메시지는 단지 오퍼레이션을 통해
무엇
이 실행되기를 바라는지만 명시하며, 어떤 메서드를 선택할 것인지는 전적으로 수신자의 결정에 좌우됩니다
다형성
- 다형성이란 서로 다른 유형의 객체가 동일한 메시지에 대해 서로 다르게 반응하는 것을 의미합니다.
- 서로 다른 타입에 속하는 객체들이 동일한 메시지를 수신할 경우 서로 다른 메서드를 이용해 메시를 이용해 메시지를 처리할 수 있는 메커니즘을 가리킵니다.
- 다형성은 역할, 책임, 협력과 깊은 관련이 있습니다. 서로 다른 객체들이 다형성을 만족시킨다는 것은 객체들이 동일한 책임을 공유한다는 것을 의미합니다. 메시지 수신자들이 동일한 오퍼레이션을 서로 다른 방식으로 처리하더라도 메시지 송신자의 관점에서 이 객체들은 동일한 책임을 수행하는 것입니다. 즉, 송신자의 관점에서 다형적인 수신자들을 구별할 필요가 없으며 자신의 요청을 수행할 책임을 지닌다는 점에서 모두 동일합니다.
- 다형성은 객체들의 대체 가능성을 이용해 설계를 유연하고 재사용 가능하게 만듭니다. 다형성을 사용하면 송신자가 수신자의 종류를 모르더라도 메시지를 전송할 수 있습니다. 즉, 다형성은 수신자의 종류를 캡슐화합니다.
- 객체지향 패러다임이 강력한 이유는 다형성을 이용해 협력을 유연하게 만들수 있기 때문입니다.
메시지를 따라라
- 객체지향 애플리케이션의 중심 사상은 연쇄적으로 메시지를 전송하고 수신하는 객체들 사이의 협력 관계를 기반으로 사용자에게 유용한 기능을 제공하는 것입니다. 클래스 기반의 객체지향 언어를 사용하는 대부분의 사람들은 객체지향 애플리케이션을 클래스의 집합으로 생각합니다. 프로그래머 입장에서는 클래스는 실제로 볼 수 있고 수정할 수 있는 구체적인 존재입니다. 대부분의 입문자들은 클래스 간의 상속 관계가 객체지향 설계를 가치 있게 만드는 핵심적인 매커니즘이라고 배웁니다. 하지만 객체지향의 강력함은 클래스가 아니라 객체들이 주고받는 메시지로부터 나옵니다.
객체지향의 애플리케이션은 클래스를 이용해 만들어지지만 메시지를 통해 정의됩니다
. - 실제로 애플리케이션을 살아있게 만드는 것은 클래스가 아니라
객체
입니다. 그리고 이런 객체들의 윤곽을 결정하는 것이 바로 객체들이 주고받는 메시지입니다. 클래스를 정의하는 것이 먼저가 아니라 객체들의 속성과 행위를 식별하는 것이 먼저입니다. 클래스는 객체의 속성과 행위를 담는 틀일 뿐입니다. - 객체 자체에 초점을 맞출 경우 가장 흔히 범하게 되는 실수는 협력이라는 문맥을 배제한 채 객체 내부의 데이터 구조를 먼저 생각한 후 데이터 조작에 필요한 오퍼레이션을 나중에 고려하는 것입니다.
- 훌륭한 객체지향 설계는 어떤 객체가 어떤 메시지를 전송할 수 있는가와 어떤 객체가 어떤 메시지를 이해할 수 있는가를 중심으로 객체 사이의 협력 관계를 구성하는 것입니다.
- 객체지향 설계의 중심에는 메시지가 위치합니다. 객체가 메시지를 선택하는 것이 아니라 메시지가 객체를 선택하게 해야 합니다. 객체지향 시스템은 협력하는 객체들의 연결망입니다.
객체 인터페이스, 구현의 분리
- 객체의 인터페이스는 객체가 수신할 수 있는 메시지의 목록으로 구성되며 객체가 어떤 메시지를 수신할 수 있는지가 제공하는 인터페이스의 모양을 빚습니다. 이때는 3가지의 원칙이 필요합니다.
- 좀 더 추상적인 인터페이스를 통해 수신자의 자율성을 보장합니다.
- 외부에서 사용할 필요가 없는 인터페이스는 최대한 노출하지 않습니다.
- 인터페이스와 구현 간에 차이가 있습니다.
- 객체가 가져야 할 상태와 메서드 구현은 객체 내부에 속합니다. 이 부분을 수정하더라도 객체 외부에 영향을 미쳐서는 안됩니다. 객체 외부에 영향을 미치는 변경은 객체의 공용 인터페이스를 수정할 때 뿐입니다. 이렇게 인터페이스와 구현의 분리 원칙은 변경을 관리하기 위한 것입니다. 느슨한 인터페이스에 대해서만 결합되도록 만드는 것입니다.
- 인터페이스를 제외한 구현부를 외부로 부터 감추는 것을
캡슐화
라고 합니다. 객체는 상태와 행위를 함께 캡슐화함으로써 충분히 협력적이고 만족스러울 정도로 자율적인 존재가 될 수 있습니다. 캡슐화를정보의 은닉
이라고 부르기도 합니다.
객체가 자율적인 책임을 갖는 것이 중요한 이유
- 책임의 자율성이 협력의 품질을 결정합니다.
- 객체의 책임이 자율적일수록 협력이 이해하기 쉬워지고 유연하게 변경할 수 있게 됩니다. 결과적으로 책임이 얼마나 자율적인지가 전체적인 협력의 설계 품질을 결정하게 됩니다.
- 자율적인 책임은 협력을 단순하게 만듭니다.
- 자율적인 책임은 외부와 내부를 명확하게 분리합니다.
- 책임이 자율적일 경우 책임을 수행하는 내부적인 방법을 변경하더라도 외부에 영향을 미치지 않습니다.(결합도가 낮아집니다)
- 자율적인 책임은 협력의 대상을 다양하게 선택할 수 있는 유연성을 제공합니다.
- 객체가 수행하는 책임들이 자율적일수록 객체의 역할을 이해하기 쉬워집니다.
- 책임이 자율적일수록 적절하게 추상화되며, 응집도가 높아지고, 결합도가 낮아지며, 캡슐화가 증진되고, 인터페이스와 구현이 명확히 분리되며, 설계의 유연성과 재사용성이 향상됩니다.
- 객체지향의 강력함을 누리기 위한 출발점은 책임을 자율적으로 만드는 것입니다.
장점
- 다른 클래스를 가져와 사용할 수 있고, 상속받을 수 있어 코드의 재사용성이 높습니다.
- 절차지향보다 유지보수가 간단하고 수정에 용이합니다.
- 클래스 단위로 모듈화가 가능하여, 대형 프로젝트에 적합합니다.
단점
- 처리속도가 상대적으로 느립니다.
- 객체가 많으면 용량이 커집니다.
- 설계시 많은 노력과 시간이 필요합니다.
OOP의 6가지 키워드
클래스
- 현실 세계의 객체를 추상화시켜, 속성과 메서드로 정의한 것입니다.(논리적 개념)
인스턴스
- 클래스에서 정의한 것을 토대로 만든 실제 메모리상에 할당된 것, 실제 데이터 입니다.
추상화
- 객체지향 관점에서 클래스를 정의하는 것입니다. 불필요한 정보 외 중요한 정보만 표현함으로써 공통의 속성과 기능을 묶어 이름을 붙이는 것입니다.
캡슐화
- 코드를 수정없이 재활용 하는 것을 목적으로 합니다. 클래스라는 캡슐에 기능과 특성을 담아 묶습니다. 목적을 기준으로 묶습니다
- 은닉화와의 차이 : 은닉화는 캡슐화의 일부라고 볼 수 있으며, 목적으로 묶인 캡슐 안을 사용자는 볼 수 없다는 것이 은닉화 입니다.
상속
- 클래스로부터 속성과 메서드를 물려받는 것입니다. 다른 클래스를 가져와서 수정할 일이 있다면, 그 클래스를 직접 수정하는 대신 상속을 받아 변경하고자 하는 부분만 변경합니다.
다형성
- 하나의 변수명이나 함수명이 상황에 따라 다르게 해석될 수 있습니다. 대표적인 다형성이 오버라이딩과 오버로딩 입니다.
OOP의 5가지 법칙 (SOLID)
Single Responsibility Principle, 단일 책임 법칙
- 각 클래스는 목적을 하나씩만 가지고 그에 대한 책임을 져야 합니다.
Open Close Principle, 개방 폐쇄 법칙
- 각 클래스는 클래스에 대한 수정을 폐쇄하고, 확장에 대해 개방해야 합니다.
- 즉 클래스를 수정해야 한다면 그 클래스를 상속, 즉 확장하여 수정합니다.
Liskov Substitusion Principle, 리스코프 치환 법칙
- 자식 클래스를 사용 중일때, 거기에 부모 클래스로 치환하여도 문제가 없어야 합니다.
Interface Segreation Principle, 인터페이스 분리 법칙
- 각 행위에 대한 인터페이스는 서로 분리되어야 합니다.
Dependency Inversion Principle, 의존성 역전 법칙
- 상위 클래스가 하위 클래스에 의존하면 안됩니다. 즉 기본적인 공통되는 속성을 하위 클래스에 의존하면 안됩니다.