프로그래밍 언어는 이해하기 어려운 기계어, 어셈블리어 자바까지 개발자르 더욱 편하고 이롭게 하기 위해 발전되어 왔다. 또한 0과 1에 대변되는 기계에 맞춰 사고하던 방식 절차적/구조적 프로그래밍을 거쳐 현실 세계처럼 프로그래밍 할 수 없을까라는 고민 속에 객체 지향의 개념이 탄생했다.
객체지향에 대해서 알아보자!
객체 : 세상에 존재하는 유일무이한 사물
클래스 : 분류, 집합. 같은 속성과 기능을 가진 객체를 총칭하는 개념
객체(Object) = 클래스(Class)의 인스턴스
추상의 사전적 의미 : 여러가지 사물이나 개념에서 공통되는 특성이나 속성 따위를 추출하여 파악하는 작용
사람 클래스
속성(Properties) : 시력, 몸무게, 혈액형, 키, 나이, 직업, 연봉 ...
행위(Method) : 먹다(), 자다(), 일하다(), 운전하다(), 입금하다(), 출금하다(), 이체하다() ...
예를 들어 병원 어플리케이션을 개발한다고 하면 사람의 직업과 연봉이라는 속성은 필요가 없을 것이다.
또한 게임 어플리케이션을 제작한다고 하면 운전하다(), 먹다(), 자다()라는 행위는 필요 없을 것이다.
🍔 개발자에게 추상화란 구체적인 것을 분해해서 관심 영역(어플리케이션 경계, Application Boundary)에 있는 특성만 가지고 재조합, 모델링 하는 것이라고 할 수 있다.개발자는 추상화를 통해 객체 지향에서 클래스를 설계하고 데이터베이스의 테이블을 설계한다.
Mouse mouse = new Mouse
클래스 멤버 : 모든 객체가 같은 값을 가질 때 사용 (ex mouse의 꼬리의 수, 자동차의 바퀴 개수)
객체 멤버 : 객체마다 다른 값을 가질 때 사용(ex 사람의 나이)
객체 지향에서의 상속 이란?
상위 클래스의 특성을 하위 클래스에서 상속(특성 상속)하고 거기에 필요한 특성을 추가, 즉 확장해서 사용할 수 있다는 의미
그러므로 일반적인 상속(Inheritence) 부모-자식이 아닌 확장(Extends) 이 더 정확한 표현
또한 자바 언어의 아버지 제임스 고슬링은 inheritence(상속)이라는 키워드 대신 extends(확장)을 씀으로써 상속이 아닌 확장이라는 의미를 냈다.
만약 인어 클래스가 사람, 물고기 두 클래스를 상속받고 있다고 했을 때 만약 두 클래스가 동일한 메서드 시그니처를 구현하고 있다면 인어 클래스는 무슨 메서드를 호출해야 할까?
다중 상속은 득보다 실이 많았기에 자바와 C#은 다중상속을 포기했다.
자바는 다중상속을 포기한 대신 인터페이스(Interface)를 도입했고, 인터페이스는 클래스가 ‘무엇을 할 수 있다’ 라고 하는 기능을 구현하도록 강제한다.
인터페이스가 어떠한 구현을 하도록 강제하기 때문에 인터페이스는 be able to(무엇을 할 수 있는)의 표현 형태로 만드는 것이 좋다.
상위 클래스는 풍성할수록 좋다 - LSP(리스코프 치환 법칙).
인터페이스는 메서드가 적을 수록 좋다 - ISP(인터페이스 분할 원칙)
같은 메서드 이름, 같은 인자 목록으로 상위 클래스의 메서드를 재정의
상속에서 상위 클래스의 특성을 상속하고 필요한 특성을 추가, 확장할 수 있다고 했는데 상속받은 특성을 변경하여 사용하는 경우 Overriding이라고 한다.
같은 메서드 이름, 다른 인자 목록으로 다수의 메서드를 중복 정의
만약 OverLoading을 지원하지 않는다면?
두 숫자를 더해서 반환하는 함수
add(int , int)
addIntDouble(int, double)
addDoubleInt(double, int)....
이런식으로 계속 확장해 나가야 한다. 아찔하다..
🍔 OverRiding을 통한 메서드 재정의, OverLoading을 통한 메서드 중복 정의를 통해 다형성을 제공하고, 이 다형성이 개발자가 프로그램을 작성할 때 사용편의성을 준다!
잘 설계된 컴포넌트는 모든 내부 구현을 완벽하게 숨겨, 구현과 API를 깔끔하게 분리한다.
개발자는 오직 공개 API를 통해서만 컴포넌트 소통하며, 컴포넌트의 내부 동작을 알 필요가 없기 때문에 훨씬 쉽게 사용할 수 있다. (내부 정보를 알 필요가 없기 때문에 어떻게 동작하는지 공부할 필요도 없는거죠!)
이렇듯 시스템을 구성하는 컴포넌트들을 서로 독립시켜서 개발, 테스트, 최적화, 적용, 분석, 수정 등을 개별적으로 할 수 있게 해줌으로써 개발에 다양한 장점을 가지게 된다.
만약 권한을 풀어주는 일을 자주 하게 된다면 → 컴포넌트를 분해해야 하는지 고려하라
“모든 클래스와 멤버의 접근성을 가능한 한 좁혀야 한다”라는 기본 원칙에 맞춰 설계를 진행함으로써
정보 은닉, 즉 내부를 숨기도록 하자!