객체 지향 4대 특성 : 추상화, 상속
1. 추상화(Abstraction) : 모델링(Modeling)
1-1. 추상화란?
클래스를 설계할 때, 이 클래스로부터 실체화 될 객체의 공통된 특성을 먼저 찾게 된다.
사람을 예로 들면 이름, 나이, 직업, 키, 혈액형 등의 속성 값을 공통적으로 가질 수 있을 것이고,
먹다, 자다, 일하다, 공부하다, 웃다 등 기능 및 행위를 나타내는 메서드를 공통으로 가질 수 있을 것이다.
사람이라는 객체를 나타내는 특성은 상기된 내용보다도 훨씬 많기 때문에
우리는 강제적으로 어느 정도까지 만들겠다는 일종의 경계(Context)가 필요하다.
그렇다면 그 경계는 어떻게 만들어 질 수 있을까.
경계는 개발하고자 하는 어플리케이션의 사용 목적에 따라 경계가 구분될 수 있다.
개발의 목적에 따라 우리는 같은 객체를 두고도 관심을 주는 영역이 명확히 구분될 수 있다.
예를 들어 병원에 관련한 어플리케이션을 개발하는 개발자는 사람이라는 객체를 '환자'로 분류하여 속성과 메서드를 부여할 것이다.
또 은행에 관련한 어플리케이션을 개발하는 개발자는 '고객'으로 분류하여
마찬가지로 '고객'이라는 객체를 나타내기에 적합한 속성과 메서드를 추려낼 것이다.
이렇듯 개발 목적에 맞는 특성만을 재조합 하는 것을 바로 '추상화', 즉 '모델링'이라고 한다.
이러한 과정을 통하여 클래스가 class 키워드를 통해 프로그램 상에 표현될 수 있게 된다.
1-2. 클래스 멤버와 인스턴스 멤버
추상화 과정을 통해 생성된 클래스에는 다양한 변수와 메서드가 사용되며,
각각 영향을 줄 수 있는 범위와 메모리 상에 저장되는 위치에도 차이가 있다.
🔹 클래스 멤버
👉 클래스가 static 영역에 배치될 때, 같은 위치에 한 번만 선언되고 어플리케이션이 중지되면 그때 소멸한다.
👉 클래스의 모든 객체가 공통되는 값을 가지는 데이터가 있다면 클래스 멤버로 선언한다.
🖍 공통 데이터가 인스턴스 멤버로 있으면 객체가 생길 때마다 새로운 저장 공간을 부여해야 하지만,
클래스 멤버로 등록해 놓으면 최초 한 번만 선언되기 때문에 메모리 측면에서 이롭다.
👉 객체의 존재 여부와 관련 없이 사용이 가능하기 때문에 일반적으로 '클래스이름.클래스멤버'로 호출한다.
🔹 인스턴스 멤버
👉 new 연산자를 통해 클래스에 따른 인스턴스가 생성되고, 생성될 때마다 개별적인 존재로 인식한다.
👉 인스턴스는 힙 영역에 배치되고 해당 인스턴스를 참조하는 변수는 스택 프레임에 배치된다.
🖍 인스턴스를 참조하는 변수가 없으면 Java에서는 이를 더는 사용하지 않는 데이터라고 판단하여 GC로 소멸시킨다.
🔹지역 변수
👉 지역 변수는 말 그대로 지정된 지역에서만 사용되고 해당 지역이 활용을 다하면 함께 소멸하는 데이터이다.
👉 별도의 초기화를 하지 않으면 쓰레기 값을 가지기 때문에 반드시 초기화를 해줘야 한다.
🖍 위의 멤버 변수들은 초기화 해주지 않으면 자동으로 선언된 타입에 맞는 값으로 초기화 된다.
멤버 변수는 다른 곳에서 접근이 가능하다는 특징이 있기 때문에 지정된 데이터 값이 없다면,
그 에러를 찾아내는 데에 시간 소모를 하게 된다.
이로 인하여 별도의 초기화를 하지 않아도 기본값을 넣어주는 것이다.
2. 상속 : 재사용
2-1. 상속이란?
객체 지향에서의 상속은 상위 클래스가 가지고 있는 특성을 하위 클래스로 상속하고
또 하위 클래스만의 개별적인 특성을 추가하는 등의 확장(extends)으로 이어지는 것을 말한다.
이러한 이유로 상위 클래스일수록 추상화, 일반화 되었고, 하위 클래스일수록 구체화, 특수화 되었다고 볼 수 있다.
상속은 다시 말해 상위 클래스의 기능을 하위 클래스에 구현하지 않아도 호출이 가능해짐을 의미하고,
이것이 바로 상속의 가장 큰 특징인 '재사용' 측면을 이야기 할 수 있다.
2-2. 인터페이스
상속 관계를 '하위 클래스 is a kind of 상위 클래스'라고 표현할 수 있다면,
인터페이스는 '구현 클래스 is able to 인터페이스'라고 표현할 수 있다.
즉 상속 관계는 하위 클래스에게 상위 클래스의 특성을 넘겨 주는 것이고,
인터페이스는 클래스에게 인터페이스라는 기능을 할 수 있음을 고지하는 것이다.
✍️ 다중 상속
Java 는 다중 상속을 지원하지 않는데, 그 이유를 설명해 보고자 한다.
예를 들어 '인어'라는 객체가 있다고 해보자.
이 인어는 '사람'의 특성을 갖기도 하면서 동시에 '물고기'의 특성을 가지고 있다.
즉 하나의 객체에 두 개의 클래스가 상속되고 있는 것이다.
이러한 상황에서 '인어' 객체에게 swim() 메서드를 실행하라고 해보자.
'사람'도 수영을 할 수 있고, '물고기'도 수영을 할 수 있기 때문에 둘 다 swim() 메서드를 가지고 있을 수 있다.
이런 경우 어느 메서드를 호출해서 실행해야 할지 알 수 없어진 '인어'는 프로그램을 종료시킬 것이다.
이러한 다중 상속의 큰 문제점을 버리고 대신 Java는 인터페이스를 구현하였다.