앞서 매서드 오버라이딩을 할 때 추상 클래스에 대해 잠깐 이야기를 했었다.
추상 클래스는 객체를 추상화 하여 인스턴스화 하지 못하게 하는 장치이다.
따라서, 추상 클래스는 두가지 특징을 가진다.
1. 추상 클래스는 new 할 수 없음(물리적이지 못해 인스턴스화 하지 못하기 때문에)
2. 추상 클래스는 추상 매서드를 가질 수 있다. 또한 일반 매서드도 가질 수 있다.
(단, 일반 클래스는 추상 매서드를 가지지 못한다)
다음의 매서드 오버라이딩 예시를 보자.
abstract class Food1 {
abstract void eat();
}
class 라면1 extends Food1{
String name="라면1";
@Override
void eat() {
System.out.println(name+"을 먹었습니다.");
}
}
class 불고기1 extends Food1{
String name="불고기1";
@Override
void eat() {
System.out.println(name+"를 먹었습니다.");
}
}
class 갈비 extends Food1 {
String name="갈비";
@Override
void eat() {
System.out.println(name+"를 먹었습니다.");
}
}
public class FoodEx01 {
static void start(Food1 f) {
f.eat();
}
public static void main(String[] args) {
start(new 라면1());
}
}
맨 위에 있는 부모 매서드 Food 앞에 abstract가 붙어 있다. 이것이 추상 매서드/클래스를 정의 하는 프로퍼티이다.
내부에 있는 매서드도 추상 매서드임을 알 수 있다.
추상 클래스를 부모 클래스로 둔 자식 클래스의 경우, 추상 클래스 내부의 추상 메서드를 반드시 오버라이딩을 통해 구현시켜주어야만 한다. 그렇지 않으면, 오버라이딩이 되지 않아 실체가 없는 추상 클래스가 호출되어 구현되기 때문에 물리적 실체가 없는 매서드가 생긴다. 따라서, 오버라이딩을 통해 실체를 구현해주어야 한다.
추상클래스의 용도를 조금만 더 알아보자.
다음의 예시를 보도록 한다.
abstract class Food{
abstract void standby();
void eat() {
System.out.println("음식을 먹습니다.");
}
protected abstract void cook();
void auto() {
standby();
cook();
eat();
}
}
class 라면 extends Food{
@Override
protected
void cook() {
System.out.println("냄비에 끓인다.");
}
@Override
void standby() {
System.out.println("냄비와 라면과 가스를 준비한다.");
}
}
class 삼겹살 extends Food{
@Override
protected
void cook() {
System.out.println("불판에 굽는다.");
}
@Override
void standby() {
System.out.println("고기와 불판, 버너를 준비한다.");
}
}
public class FoodEx02 {
static void start(Food f) {
f.auto();
}
public static void main(String[] args) {
start(new 라면());
}
}
추상 클래스는 자신이 구현하지 못하는 매서드를 오브젝트에 미룰 수 있다.
잘 생각해보자.
음식을 먹는 것은 어느 음식이나 다 같기 때문에 구현이 가능하다. 따라서 굳이 다른 오브젝트에게 미룰 필요는 없다. 그러나 음식을 준비하는 것이라던지, 조리 과정은 호출될 자식 클래스에 따라 다르게 나타나기 때문에 부모클래스에서 구현할 수 없다. 따라서 실체화 될 객체에게 미루게 된다.
추상클래스는 은닉화를 진행할 수 없다. 오버라이드 해야하기 때문이다.
대신 protected 는 사용할 수 있는데, 이 프로퍼티는 자식 클래스만 이용하게 만들 수 있다. 대신 오버라이드 된 매서드 앞에 proctected를 붙여주는 것을 잊지 않도록 한다.
auto 매서드는 매서드의 순서를 정해주는 매서드이다.
추상 클래스는 다른 용도로도 사용할 수 있다.
abstract class 칼{
abstract void kill();
abstract void cook();
abstract void repair();
}
class 백종원 extends 칼{
@Override
void kill() {
}
@Override
void cook() {
}
@Override
void repair() {
}
칼은 다음과 같은 일을 할 수 있다.
무언가를 죽이는데도, 요리를 할 때도, 다른 부러진 물건을 수리할 때도 사용할 수 있다.
하지만 요리사는 칼을 요리할 때만 사용한다.
그러나, 추상 클래스로 이를 묶으면 세 개의 매서드를 반드시 오버라이딩 해야해서 문제가 생긴다.
하지만 죽이는 것과 요리하는 것, 수리하는 것은 추상적인 행동이다.
이것을 방지하려고 하면 어떻게 해아할까.
이를 위해 한번 더 추상 클래스를 사용한다.
abstract class 칼{
abstract void kill();
abstract void cook();
abstract void repair();
}
abstract class 요리사어댑터 extends 칼{
@Override
void kill() {
}
@Override
void repair() {
}
}
class 백종원 extends 요리사어댑터{
@Override
void cook() {
}
}
요리사(백종원) 앞에 새 추상 클래스를 걸어 먼저 kill 과 repair 매서드를 공백으로 실체화 시킨다. 그렇게 되면 그 아래 자식 클래스인 요리사는 cook 매서드 하나만 실체화 시키면 된다. 이렇게 추상 클래스 내에 일반 클래스를 걸어 먼저 실체화 시키는 클래스를 '어댑터' 라고 부른다. 추상 클래스는 다음과 같은 역할을 하기도 한다.
'JAVA' 카테고리의 다른 글
12. 컴포지션 (0) | 2020.04.03 |
---|---|
11. 인터페이스 (0) | 2020.03.31 |
라이브러리(lombok) 설치하기 (0) | 2020.03.31 |
JAVA 실습 6. 매서드 오버라이딩을 이용한 오버로딩 줄이기 (0) | 2020.03.30 |
9. 매서드 오버라이딩 (0) | 2020.03.30 |