[java] 15. 추상클래스


추상클래스



클래스를 설계도에 비유한다면, 추상클래스는 미완성 설계도에 비유할 수 있습니다.

미완성 설계도란, 단어의 뜻 그대로 완성되지 못한 채로 남겨진 설계도를 말합니다.

클래스가 미완성이라는 것은 멤버의 개수에 관계된 것이 아니라,

단지 미완성 메서드(추상 메서드)를 포함하고 있다는 의미입니다.

미완성 설계도로 완성된 제품을 만들 수 없듯이 추상클래스로 인스턴스는 생성할 수 없습니다.

추상클래스는 상속을 통해서 자식클래스에 의해서만 완성될 수 있습니다.

추상클래스 자체로는 클래스로서의 역할을 다 못하지만,

새로운 클래스를 작성하는데 있어서 바탕이 되는 부모클래스로서 중요한 의미를 갖습니다.

새로운 클래스를 작성할 때 아무 것도 없는 상태에서 시작하는 것보다는 완전하지는 못하더라도

어느정도 틀을 갖춘 상태에서 시작하는 것이 나을 것입니다.

추상클래스는 키워드 abstract를 붙이기만 하면 됩니다.


abstract class 클래스이름{

}



추상클래스는 추상메서드를 포함하고 있다는 것을 제외하고는 일반클래스와 전혀 다르지 않습니다.

추상클래스에도 생성자가 있으며,

멤버변수와 메서드도 가질 수 있습니다.



추상메서드



메서드는 선언부와 구현부로 구성되어 있는데, 선언부만 작성하고 구현부는 작성하지 않은 채로

남겨 둔 것이 추상메서드입니다.

즉, 설계만 해 놓고 실제 수행될 내용은 작성하지 않았기 때문에 미완성 메서드인 것입니다.

메서드를 이와 같이 미완성 상태로 남겨 놓는 이유는 메서드의 내용이 상속받는 클래스에 따라

달라질 수 있기 때문에 부모 클래스에서는 선언부만 작성하고,

주석을 덧붙여 어떤 기능을 수행할 목적으로 작성되었는지 알려 주고,

실제 내용은 상속받는 클래스에서 구현하도록 비워두는 것입니다.

추상메서드 역시 키워드 abstract를 앞에 붙여 주고, 추상메서드는 구현부가 없으므로 괄호{} 대신

문장의 끝을 알리는 ;을 적어줍니다.


/* 주석을 통해 어떤 기능을 수행할 목적으로 작성하였는지 설명한다. */
abstract 리턴타입 메서드이름();



추상클래스로부터 상속받는 자식클래스는 오버라이딩을 통해

부모인 추상클래스의 추상메서드를 모두 구현해주어야 합니다.

만일 부모로부터 상속받은 추상메서드 중 하나라도 구현하지 않는다면,

자식클래스 역시 추상클래스로 지정해 주어야 합니다.


abstract class Player{//추상 클래스
	abstract void play(int pos); //추상 메서드
	abstract void stop(); //추상메서드
}

class AudioPlayer extends Player{
	void play(int pos{/* 내용 생략 */}; //추상 메서드 구현
	void stop(){/* 내용 생략 */}; //추상 메서드 구현
}

abstract class AbstractPlayer extends Player{
	void play(int pos){/* 내용 생략 */}; //추상 메서드를 구현
}



위의 코드에서 AbstractPlayer 클래스는 stop 추상 메서드를 구현해주지 않았기에

클래스 명 앞에 abstract을 붙여서 추상클래스로 선언해야합니다.



추상클래스의 작성



여러 클래스에 공통적으로 사용될 수 있는 클래스를 바로 작성하기도 하고,

기존의 클래스의 공통적인 부분을 뽑아서 추상클래스로 만들어

상속하도록 하는 경우도 있습니다.

상속이 자식클래스를 만드는데 부모 클래스를 사용하는 것이라면,

이와 반대로 추상화는 기존의 클래스의 공통부분을 뽑아내서 부모클래스를 만드는 것이라고 할 수 있습니다.

추상화를 구체화와 반대되는 의미로 이해하면 보다 쉽게 이해할 수 있을 것입니다.

상속계층도를 따라 내려갈수록 클래스는 점점 기능이 추가되어 구체화의 정도가 심해지며,

상속계층도를 따라 올라갈수록 클래스는 추상화의 정도가 심해진다고 할 수 있습니다.


추상화 클래스간의 공통점을 찾아내서 공통의 부모를 만드는 작업

구체화 상속을 통해 클래스를 구현, 확장하는 작업



아래는 Example라는 추상클래스입니다.


abstract class Example{
	int a;
	
	abstract void method(int num); //추상메서드
}



위의 추상클래스는 상속을 통해 method를 오버라이딩하여 구체적인 내용을 작성해주어야합니다.

굳이 abstract를 하지말고 다음과 같이 하면 어떨까요?


class Example{
	...
	void method(int num){}; //아무런 내용이 없는 메서드
}



아무런 내용도 없이 단지 괄호{}만 있어도, 추상메서드가 아닌 일반 메서드로 간주되기 때문에

위의 코드는 자식 클래스에서 오버라이딩 할 수도 있고 안 할 수도 있습니다.

따라서 자식클래스에서 추상메서드를 반드시 구현하도록 강요하기 위해서는 abstract를 붙이는 것이 좋습니다.

또한, 추상클래스는 아까 말했듯이 미완성 설계도이기에 객체를 생성할 수 없습니다.

예를 들어 다음과 같은 코드는 컴파일 오류를 발생시킵니다.


Example ex=new Example(); //추상클래스 인스턴스 생성 시도



하지만, 추상클래스 참조변수가 자식클래스의 인스턴스를 참조하는 것은 가능합니다.


Example[] ex=new Example[4];

ex[0]=new Child1(); //추상클래스 참조변수가 자식클래스 인스턴스를 참조 

ex[1]=new Child2();

ex[2]=new Child3();

ex[3]=new Child4();