저를 포함한 초보자분들에게 도움이 됐으면 좋겠습니다.
초보자분들은 수박 겉핥기 식으로 알고 넘어가지 마시고, 조금이라도 왜 이렇게 프로그램이 돌아가는지 알고 가시는 시간이 됐으면 좋겠습니다.

오늘은 클래스 중 추상 클래스(abstract)를 살펴보죠.
'추상'이라는 단어의 뜻을 알고 계시나요?
국어사전에는 '여러 가지 사물이나 개념에서 공통되는 특성이나 속성 따위를 추출하여 파악하는 작용'
이라고 적혀있습니다.
자바에서도 추상 클래스(abstract)는 국어사전의 의미와 동일합니다.
자바에서는 공통이 되는 메소드를 파악해 추상메소드를 만드는 것이 추상 클래스에서 가장 중요합니다.
간단한 예를 들어보죠. 넓이를 구한다고 생각해봅시다. 그럼 네모의 넓이는 어떻게 구하나요? x, y 값을 곱하여 구합니다. 그럼 세모는요? x * y / 2를 하면 됩니다. 누구나 알고 있는 것이죠.
하지만 이걸 이제 클래스로 표현해야 한다면 어떻게 하실 건가요? 혹시 세모 클래스, 네모 클래스를 각각 만들어 사용하실 건가요? 그러기엔 x, y좌표가 있어야 하고 넓이를 구하는 메소드가 있다는 공통점이 눈에 띄지 않나요? 

위 국어사전의 '정의처럼 공통되는 특성이나 속성 따위를 추출'하여 새로운 클래스를 구성해 보면 어떨까요? 소스코드를 보시죠.

(1)public class shape {
	  int x;
	  int y;
	  public void area() { //??????
	  }
}
==================================
public class rectangle extends shape { }
==================================
public class triangle extends shape{ }

(1) 소스코드와 같이 shape란 클래스를 만들어서 네모, 세모에 공통이 되는 부분을 모두 넣은 클래스를 만들었습니다. 이와 같이 shape란 클래스를 만들어서 상속 형태로 사용하는 것이 이상적이라 볼 수 있습니다. 하지만 문제가 있습니다. 네모, 세모의 넓이를 구하는 메소드(area)는 각자 넓이를 구하는 공식이 다르다는 것입니다. 하지만 '넓이'를 구해야 한다는 속성은 변함이 없어 shape에 공통된 메소드로 들어가게 되는 것이죠. 이 문제를 어떻게 해결할 수 있을까요? '오버라이딩'이 단숨에 생각이 나셔야 합니다.
오버라이딩을 사용하여 rectangle, triangle 각각 클래스에서 재지정하여 넓이를 구해야 하죠.
하지만 우리가 배운 '오버라이딩'은 부모 클래스에 메소드가 온전히 정의가 되어있을 때 사용했었습니다. 여기서 생각해 봐야 하는 부분은 shape에 넓이를 구하는 메소드가 완전히'정의'될 필요가 있는가입니다. 이 뜻은 shape 안에 area는 반드시 자손 클래스에 가서 서로 다른 형태로 사용된다고 우리는 이미 알고 있습니다. 그럼 shape 안에서 완전하게 정의가 될 필요는 없는 거죠. (완전히 정의된다는 것은 메소드가 수행하는 부분 { }이 들어가야 한다는 뜻)
그래서 사용하는 게 abstract 키워드입니다. abstract 키워드는 간단하게 말해서 상속받는 부분에서 '반드시' abstract로 된 메소드를 반드시 정의해주겠다는 소리입니다!
예제를 보시죠!

(2)public abstract class shape { //하나라도 추상메소드가 있으면 추상클래스가 되야함!
	int x=2;
	int y=2;
	
	public abstract void area(); // abstract 메소드! 
}
======================================
public class rectangle extends shape {
	@Override //오버라이드!
	public void area() {
		System.out.println(this.x*this.y);
	}
}
=======================================
public class triangle extends shape{
	@Override
	public void area() {
		System.out.println(this.x*this.y/2);
	} 
	public static void main(String args[]) {
		new rectangle().area();
		new triangle().area();
	}
}

(2)와 같이 (1)의 코드를 고쳐보았습니다. 가장 눈에 띄는 건 shape의 area를 abstract 키워드를 사용하여 추상메소드로 선언했다는 것입니다. 이렇게 되면, shape 자체 area메소드는 실질적으로 구하는 공식이 없어 훨씬 추상적이게 되는 것이죠.(공통적이 부분을 잘 뽑아내게 되는 것이죠)
하지만 반드시 추상메소드를 선언하게 되면 추상메소드가 속한 클래스는 반드시 추상 클래스가 돼야 합니다. 추상메소드가 하나라도 있게 된다면 추상 클래스가 되는 것이죠. 추상 클래스가 된다고 해서 클래스와 크게 바뀌는 것은 없습니다. 단, 추상 클래스를 상속받는 클래스는 추상메소드를 '반드시' 클래스 안에서 재정의 해야 합니다.(오버라이딩과 같이 말이죠)

하지만 의문점이 하나 생길 수 있습니다. 그럼 rectangle, triangle 따로따로 area 메소드를 사용하면 되는 거 아니냐?라는 점입니다. 물론 맞는 말입니다. 상관없습니다. 하지만.. 지금처럼 추상화를 잘 해놓게 된다면 이점이 있습니다. '형식'을 가지게 되는 것입니다. 살면서 한 번씩은 보고서, 자기소개서, 리포트 등등.. 을 써보셨을 겁니다. 혹시 백지인 A4용지에 구구절절 써 내려가는 것과 '형식'이 적혀있는 A4 종이에 맞춰 적어 내려가는 것 중 어느 것을 선택할 건가요? 대개 '형식'이 있는 것을 선택하지 않을까요? 
이 '형식'을 통하여 작성자는 어떤 것을 써 내려가야 하는지 방향성을 알 수 있지 않을까요?
자바에서도 마찬가지라고 생각합니다. '형식'을 만들어 방향성을 제시하고 추후에도 재사용 하겠다는 의미입니다. 추상화 클래스를 잘 구성하게 된다면, 보다 짜임세있는 '형식'을 가지는 코드를 작성할 수 있지 않을까요? 오늘은 여기까지입니다!

오늘은 추상클래스(메소드)편을 살펴보았습니다. 어려운 것은 없었습니다. 다시 한번 잘 생각해보시고 '추상화'가 줄 수 있는 이점에 대해서 살펴보시는 것도 좋을 것 같습니다. 

다음 편은 Interface(인터페이스)를 살펴보고 추상 클래스와 비교까지 해보도록 하겠습니다.

+ Recent posts