본문 바로가기

Programming/JAVA

java : interface와 abstract를 이용해서 자손클래스들에게 바른 길을 안내해주세요.

우선 이 글을 이해하기 위해서는 추상화와 구체화가 무엇인지 알아야합니다.
추상화와 구체화는 OOP 카테고리에 설명해놓았습니다. 먼저 참고해주시면 감사하겠습니다. :)

java가 재사용성을 지원해주고 객체지향적 코딩을 지원해주기에 선택한 탁월한 방법.
바로 abstract와 interface 키워드입니다.

우선 interface에 대해서 알려드리자면 추상화의 정도가 높은 클래스를 알리는 키워드로서
interface 클래스는 상수멤버만 가지고 멤버변수를 가지고 있지 않을 뿐더러
가지고 있는 모든 메서드는 구현되어있지 않습니다.
실제 소스로의 구현은 밑과 같습니다.
interface TestInterface{
   public static final int MAX = 10;
   int MIN = 0;  // public static final 상수들은 interface클래스들의 default 상수선언형식으로 키워드는 생략가능합니다.
   public abstract int setSize();
   int getSize(); // public abstract 메소드들은 interface클래스들의 default 메소드형식으로 키워드는 생략가능합니다.


java는 다중상속을 지원하지 않는 대신에 위와 같은 interface를 여러개 상속받을 수 있습니다.
키워드는 implements를 사용합니다.
(interface는 객체지향적 프로그래밍을 지원하기 위해 나온 키워드로 상속개념을 가지고 있습니다.
 interface 상속에 대해서는 나중에 다시 알려드리겠습니다.)

abstract키워드는 해당 클래스에는 완성되지 않은 코드가 있음을 알리는 기능을 합니다.
(해당 클래스는 일반 클래스와 다를게 없지만 반드시 완성되지 않은 메소드를 가지고 있습니다.
 완성되지 않은 메소드는 abstract 키워드를 가지고 있습니다.)
따라서 abstract키워드를 가진 클래스를(abstract class라고 합니다)
상속하는 클래스들은 완성되지 않은 코드를 구현해주어야 합니다.
abstract 클래스들은 일반 클래스와 같이 extends 키워드를 통해서만 상속이 가능합니다.
abstract 키워드에 대해서는 별로 비중을 두고 싶지 않습니다. 그 이유는 상속에 대한 이해가 되어있고
추상화가 무엇인지 이해된다면 interface class와 일반 class의 중간 역할정도로 이해해도 무방되기 때문입니다.

그럼 실제 예제를 보면서 이해를 도와드리겠습니다.
동생이 어느날 시간표를 개발해달랍니다.
그럼 이렇게 프로그램을 짤 수 있습니다.
class 시간표{
   Date 날짜;
   String 데이터;
   public void 입력(){ // 날짜를 입력받고 데이터 입력받기 };
   public void 출력(){ // 월간 표를 출력하여 날짜별 데이터 출력해주기 };
}

처음에는 동생이 고맙다고하지만 이내 다시 오더니 날짜를 검색하고 싶다고 합니다.
그래서 바로 소스를 좀 고쳐서 만들어줍니다.
class 시간표{
   Date 날짜;
   String 데이터;
   public void 입력(){ // 날짜를 입력받고 데이터 입력받기 };
   public void 출력(){ // 월간 표를 출력하여 날짜별 데이터 출력해주기 };
   public void 검색(){ // 날짜를 검색해주기 };
}

다시오더니 출력을 일일, 주, 월별로 해달랍니다. 그냥 콱 쥐어박을까 고민해보지만
다음부터 심부름시킬 때 말 안들을 것 같고해서 그냥 해주려고 소스를 열어봅니다.
갑자기 귀차니즘이 밀려옵니다. 동생이 언젠가는 구글 캘린더처럼 출력뿐만 아니라 입력도
다중선택해서 기록할 수 있기를 희망할 것 같습니다.
음... 공통된 것들을 우선 빼봅니다. 입력과 출력기능이 반드시 필요하지만 일, 주, 월 별로는 각기 다르겠죠.
그리고 서칭, 날짜과 날짜도 반드시 필요한데 이것들은 공통된 기능이네요!
interface 시간표IO{
   void 입력(){}
   void 출력(){}
}
interface 날짜검색{
   void 검색(){}
}

우선 어떤 기능들이든 반드시 필요한 것을 interface 선언으로 강제합니다.
혹시 모를 귀찮은 동생이 요구사항을 더 늘릴 수 있으니까요!

그리고 공통된 기능들을 구현해볼까요? 마찬가지로 요구사항이 더 늘 것을 인식하고 추상메서드를 만들어야겠어요!
abstract class 추상시간표 implements 시간표IO, 날짜검색{
   Date 날짜;
   String 데이터;
   void 검색(){ // 날짜를 검색하기 구현~ }
   abstract void 입력(){} 
   abstract void 출력(){} 
}

자 이제 추상시간표를 통해 어떤 날짜이든지 검색을 하여서 동생은 그 날 무슨 일을 하였었는지 알 수 있습니다.
그럼 일, 주, 월 별로 입력받고 출력해주는 것을 작성해볼까요?
class 일_시간표 extends 추상시간표{
   void 입력(){ // 일별로 입력을 받아요~ }
   void 출력(){ // 일별로 출력을 해줘요~ }
}
class 주_시간표 extends 추상시간표{
   void 입력(){ // 주별로 입력을 받아요~ }
   void 출력(){ // 주별로 출력을 해줘요~ }
}
class 월_시간표 extends 추상시간표{
   void 입력(){ // 월별로 입력을 받아요~ }
   void 출력(){ // 월별로 출력을 해줘요~ }
}

위처럼 시간표를 개발할 수 있습니다.
우선 어떠한 시간표이든 꼭 필요한 것들을 interface로 만들어주고
반드시 필요한 메소드들을 선언해놓습니다.
abstract 클래스는 시간표들이 공통으로 가지고 있는 기능들을 구현해주고
공통으로 가지고 있고 필요하지만, 실제 로직이 다른 기능들에 대해서는 abstract 메소드로 선언해놓아줍니다.
그리고 abstract 클래스를 상속받는 클래스들은 abstract 메소드만 실제 구현해줍니다.

이렇게되면 후에 어떠한 시간표를 원하게 되든 입력과 출력의 차이점만 구현해주고
추상시간표를 상속받는다면 날짜검색을 통해 시간표기능들을 사용할 수 있습니다.

interface와  abstract 클래스의 역할, 그리고 사용방법에 대해 이해가 되셨나요?
이런 추상화작업은 자주 손에 익혀두지 않는다면 잊혀지게 되니,
주변 사물들을 객체지향적 사고를 통해 바라보는 습관을 가지면 좋습니다.
저도 자주 못하지만 하려고 노력하니 무척 재밌어요 ㅎㅎ