오늘 공부할 것은 추상화이다.
의미만 보면 간단하지만 우리의 과제는 '공통분모의 캡슐화'이다.
A 캡슐과 B 캡슐의 공통분모를 뽑아내서 -> O 캡슐을 만들어야 한다.
//도형 (추상클래스)
//네모, 세모, 원, 선
//성적 (추상클래스)
//ㅁ고등학교, o고등학교..
위 처럼 추상화로 만들어진 클래스의 특징이 있다.
- 추상 클래스는 뼈대이므로 실체화(객체화) 되어서는 안됨.
- 추상 클래스는 뼈대이므로 절대로 사용해서는 안되는 메소드를 가질 수 있다.
1번을 위한 자바의 기능은 abstract이다.
public abstract class Exam {
private int kor;
private int eng;
private int math;
...
}
abstract 키워드를 사용해 추상클래스 Exam을 만들었다.
추상클래스의 인스턴스화를 시도했더니 에러가 발생하였다.
이렇게 abstract를 이용해 인스턴스화를 막을 수 있다.
그렇다면, 추상화를 하여 클래스를 만들었지만 그 추상클래스의 인스턴스화가 필요하다면?
abstract 키워드를 빼면 된다.
추상 클래스는 마음으로 정하는 것이지,
abstract가 붙었으니 추상클래스이다? -> 이건 옳지 않다.
abstract를 붙이지 않아도 추상화된 클래스이면 추상클래스이다.
요약하자면
추상화하여 클래스를 만들 때
그 클래스가 객체화되는 것을 막고싶다면 abstract 키워드를 붙이고
그렇지 않다면 붙이지 않으면 된다.
2번에 대해 이야기해보자.
public abstract class Exam {
...
public float avg() {
return total()/3.0f;
}
...
}
public class NewExam extends Exam {
@Override
public float avg() {
return total() / 4.0f;
}
}
추상클래스인 Exam 클래스의 avg() 메소드는 자식객체를 사용할때 호출될 일도 없고 호출 되어서도 안된다.
그러면 Exam 클래스의 avg() 메소드를 아예 지워버리면 되지 않나?
왜 굳이 오버라이딩을 해야할까
Exam exam = new NewExam();
위 코드 처럼 Exam(부모)형 변수로 NewExam(자식)객체를 참조하기 위해서이다.
(접근가능 함수 범위는 전 게시글에 있다.)
그렇다면 왜 부모형식으로 자식객체를 참조하는 것이 왜 필요할까?
자식들을 한번에 묶을 수 있는 도구로 사용하여, 일괄적으로 관리하기 위함이다.
다시 본론으로 돌아와서,
avg() 메소드는 어떻게 처리할 수 있을까
마찬가지로 abstract 키워드이다.
public abstract class Exam {
...
public abstract float avg();
//중괄호는 생략됨.
...
}
avg() 메소드를 추상화 시킨 것이다.
이렇게 하면 메소드의 구현은 자식의 몫이 된다. 구현의 부채감을 자식에게 넘겨버리는 것이다!
요약하자면,
- 굳이 부모클래스에서 쓰지도 않을 메소드를 구현하기 싫다..
- 그렇다고 지워버리자니 부모형식으로 자식객체를 참조할 때(일괄처리!) 에러가 나네
- abstract 키워드 붙이고 구현은 자식한테 넘겨버리자!