Java 언어는 객체지향 언어로, 현실 사물을 "속성"과 "기능"을 가진 객체로 묘사합니다.
또한 객체간의 관계를 맺어 주어 이해하기 쉽도록 만듭니다.
이 글에서는 Java 언어가 객체간의 "관계"를 설정하는 방법에 대해 다뤄보겠습니다.
상속 관계 (Inheritance)
두 객체간에 IS-A 관계 (~는 ~이다) 로 이어지는 관계를 보통 상속관계라고 합니다.
자바에서는 코드의 재사용성, 유지보수, 신뢰성을 유지하기 위해 클래스 간 상속관계를 도입하였습니다.
Java 코드로 묘사한 "물건" 클래스를 통해 상속관계를 이해해봅시다.
“물건을 묘사하는 클래스, 확장가능성이 높은 클래스이다.”
/**
* 물건을 묘사하는 "객채" 입니다.
*/
public class Thing {
// 물건은 "모양" 속성을 가집니다.
String shape;
// 물건은 "색" 속성을 가집니다.
String color;
// 물건은 "주인" 속성을 가집니다.
String owner;
public void touchThing() {
// 누군가가 "만질 수 있는" 기능이 있습니다.
System.out.println("touch");
}
public void useThing() {
// 누군가가 "사용할 수 있는" 기능이 있습니다.
System.out.println("use");
}
}
"물건(Thing)"은 우리가 현실에서 여러 가지 사물을 묘사할 때 많이 쓰는 포괄적인 단어입니다.
지시대명사인 "그것", "저것" 처럼 수 많은 사물을 뭉뚱그려 한 단어로 설명할 수 있는 개념이죠.
이렇게 여러 사물에서 공통된 특성을 뽑아내어 더 적은 수의 단어로 묘사하는 것을 "추상화" 라고 합니다.
즉 "사물" 은 자동차, 컴퓨터와 같은 여러 구체적인 것들에서
"물질로 구성되었다"라는 공통된 측면을 뽑아서 한 단어로 묘사한 것입니다.
제가 만든 클래스인 Thing은 현실의 단어 "사물"을 바탕으로 묘사한 것이므로
물질로 된 것이라면 무엇이든지 묘사할 수 있습니다.
이렇게 많은 개념의 공통된 특성을 하나의 클래스로 묘사한다면 "확장성이 높다" 라고 말 할 수 있겠습니다.
실제로 이 Thing을 확장시켜 보겠습니다.
“기계를 묘사하는 클래스, 물건에서 확장된 개념이다. “
/*
* 기계를 묘사하는 "객체"입니다.
* */
public class Machine extends Thing{
//기계는 "동력원" 을 속성으로 가집니다.
String energySource;
// 기계는 "부품"을 속성으로 가집니다.
String part;
public void activate() {
// 기계는 "작동할 수 있는" 기능이 있습니다.
System.out.println("activated");
}
public void shutDown() {
// 기계는 "멈출 수 있는" 기능이 있습니다.
System.out.println("SHUTDOWN");
}
}
맨 윗줄을 보면 class Machine .. 으로, 기계(Machine)이라는 이름의 클래스를 만든 것을 보실 수 있습니다.
그런데 Thing과는 달리, 뒷줄에 두 단어가 더 붙어있습니다.
'extends'와 'Thing'입니다.
Thing(사물)을 extends(확장) 시켜서 더 구체적으로 묘사한 결과가 Machine(기계)가 된다는 것입니다.
"기계"는 다른 사물에는 없는 고유한 "속성"과 "기능"도 있습니다.
'돌'은 같은 Thing일지는 몰라도 클래스에 정의된 속성 energySource 와 part를 가질 수는 없습니다.
돌이 activate(작동) 하거나 shutDown(멈춤) 같은 기능이 있다고 보기도 어렵습니다.
즉, 여기서의 Machine 클래스는 Thing 클래스가 가진 속성과 기능을 가지면서도
자신의 고유한 속성과 기능을 추가로 가지는 클래스가 된 것입니다.
바로 그렇기 때문에 Thing에서 "확장" 되었다고 말 할 수 있겠습니다.
이렇게 Java에서는 A extends B 라는 문법으로 A와 B를 "상속 관계" 로 만듭니다.
두 객체간의 관계를 extends 라는 문법으로 확실히 정의해 주는 것입니다.
객체 A (예를 들어, Thing)은 얼마든지 다른 객체로 "확장될" 수 있습니다.
게다가 물건이 꼭 기계만 있는 것은 아니기 때문에
Thing extends Cup, 역시 개념적으로 아무런 문제가 없습니다.
객체 A는 무수히 많은 B와 상속관계를 맺을 수 있는 것입니다.
“자동차를 묘사하는 클래스, 기계에서 확장된 개념이다.”
/**
* 자동차를 묘사하는 "객채" 입니다.
*/
public class Car extends Machine{
// 차는 "엔진 회전수"를 속성으로 가집니다.
String bpm;
// 차는 "자동차 바퀴 갯수"를 속성으로 가집니다.
int numberOfTire;
// 차는 "주행거리"를 속성으로 가집니다.
long distanceDriven;
// 변수가 아닌 Class를 통해서 차와 - 부품들의 Has-a 관계를 묘사합니다.
// 클래스는 다른 클래스를 "속성"으로 가질 수 (HAS-A) 있습니다.
CarSheet carSheet = new CarSheet();
Engine engine = new Engine();
Wheel wheel = new Wheel();
public void drive(String owner) {
//차는 "운전할 수 있는" 기능이 있습니다.
System.out.println(owner + "drives the car");
}
public void useAirConditioner(String bpm) {
//차는 "에어컨을 돌릴 수 있는" 기능이 있습니다.
System.out.println("car use AirConditioner with his " + bpm + "bpm Engine");
}
}
이번에는 상속관계에 대해 좀 더 깊이 들어가 보도록 하겠습니다.
현실 자동차의 속성과 기능을 가지는 Car 클래스를 만들어 봅시다.
이번에도 역시 Car extends Machine 이라는 문법을 통해서 Machine을 확장시켜 Car을 묘사하고 있습니다.
그런데, 앞에서 선언했듯이 Machine은 Thing을 확장시켜 만든 클래스입니다.
즉, Car은 Machine을 확장시켜 만들었으니, Thing에도 포함되는 게 확실하겠군요.
이렇게 상속관계는 서로다른 두 객체만 관계가 생기는 것이 아니라,
상속을 받은 ( 확장된 ) 객체가 또 다른 객체와 상속관계를 맺으면 꼬리에 꼬리를 물고 이어지게 됩니다.
결국 Car을 다시 확장해서 벤츠(Benz)를 만들면 "물건(Thing)" 이면서 "기계(Machine)"이면서 "차(Car)"이므로
벤츠는 저 세 가지 객체의 속성과 기능을 모두 가지게 되는 것입니다.
이런 상속관계를 세밀하게 묘사하면 어떤 장점이 있을까요?
먼저 같은 코드의 재사용성이 높아집니다.
만약 Thing을 상속하지 않았다면, 기계나 자동차에게 "색깔" 속성이나 "만질 수 있는" 기능을 일일히 붙여넣어 주어야 합니다.
그러나 상속관계를 통해 속성과 기능을 공유하도록 만들었기 때문에 그럴 필요가 없습니다.
Thing의 속성과 기능을 정의하는 코드는 앞으로 extends Thing 두 단어만 사용하면 어떤 클래스에든 재사용할 수 있습니다.
코드의 유지보수도 역시 쉬워집니다.
만약 내가 만드는 모든 자동차를 "가솔린" 차량으로 만들고 싶다면, energySource를 검증하는 기능을 하나 만들어주기만 하면 됩니다.
public boolean checkIsGasolineCar() {
if(energySource.equals("gasoline")) {
return true;
} else {
return false;
}
}
게다가 코드에 대한 이해도가 매우 높아집니다.
만약 제가 DAS;KJFADFA9124109248S 라는 클래스를 만든다고 가정한다면, 이 코드만으로는 대체
무엇을 묘사하고자 하는지 알기 힘들 것입니다.
그러나 'DAS;KJFADFA9124109248S extends Car ' 라는 문법을 통해 Car 클래스와의 관계를 만들어 준다면
코드를 읽는 사람이 "아 이 DAS;KJFADFA9124109248S는 Car과 관련있거나, 혹은 Car의 한 종류이겠군" 이라고
제가 짠 코드의 맥락(Context)을 금방 파악할 수 있을 것입니다.
이렇게 상속관계를 세밀하게 묘사하면 객체지향 언어가 가지는 장점인 높은 재사용성, 쉬운 유지보수 뿐만아니라
다른 사람도 이해하기 쉽고, 나중에 자신이 읽어도 금방 기억할 수 있는 코드가 됩니다.
Java 언어를 사용하실 때는 이러한 장점들을 가진 "상속"을 꼭 사용해 보시기를 바랍니다.
'플라자' 카테고리의 다른 글
SPI, Service Provider Interface ( 서비스 제공자 인터페이스 ) (0) | 2022.07.17 |
---|---|
JAVA의 객채지향 (0) | 2022.06.12 |