추상 클래스 & 추상 메소드 예시 - 이상한 나라의 앨리스
왕, 왕비 = 판사 / 모자장수, 토끼 = 증인
판사와 증인은 abstract 추상클래스라서 new 불가능.
오버 로딩 ver
package ex06.example5;
class 왕{
public void 심문() {
System.out.println("왕은 심문한다");
}
}
class 모자장수{
public void 대답() {
System.out.println("모자장수는 대답한다");
}
}
public class AliceApp {
public static void main(String[] args) {
왕 u1 = new 왕();
모자장수 u2 = new 모자장수();
u1.심문();
u2.대답();
}
}

왕이 아니라 왕비가 심문하는 걸로 바꾸고 싶다.
> 왕비 클래스를 하나 생성
package ex06.example5;
class 왕{
public void 심문() {
System.out.println("왕은 심문한다");
}
}
class 왕비{
public void 심문() {
System.out.println("왕비는 심문한다");
}
}
class 모자장수{
public void 대답() {
System.out.println("모자장수는 대답한다");
}
}
public class AliceApp {
public static void main(String[] args) {
왕비 u1 = new 왕비();
모자장수 u2 = new 모자장수();
u1.심문();
u2.대답();
}
}

왕비로 바뀐 것 확인. 토끼라는 증인을 추가한다.
package ex06.example5;
class 왕{
public void 심문() {
System.out.println("왕은 심문한다");
}
}
class 왕비{
public void 심문() {
System.out.println("왕비는 심문한다");
}
}
class 모자장수{
public void 대답() {
System.out.println("모자장수는 대답한다");
}
}
class 토끼{
public void 대답() {
System.out.println("토끼는 대답한다");
}
}
public class AliceApp {
public static void main(String[] args) {
왕비 u1 = new 왕비();
토끼 u2 = new 토끼();
u1.심문();
u2.대답();
}
}

정말 번거롭다. 이제 왕, 왕비, 토끼, 모자장수 메소드의 통로가 될 추상메소드를 만들자
1. 추상화 시키기 ★
package ex06.example5;
class 판사 {
public void 심문() {} //껍데기만 만들기, 판사를 통로로만 사용
}
class 증인 {
public void 대답() {}
}
class 왕 extends 판사 {
public void 심문() {
System.out.println("왕은 심문한다");
}
}
class 왕비 extends 판사 {
public void 심문() {
System.out.println("왕비는 심문한다");
}
}
class 모자장수 extends 증인 {
public void 대답() {
System.out.println("모자장수는 대답한다");
}
}
class 토끼 extends 증인 {
public void 대답() {
System.out.println("토끼는 대답한다");
}
}
public class AliceApp {
public static void main(String[] args) {
판사 u1 = new 왕비(); //heap 메모리에 [판사, 왕비]
증인 u2 = new 토끼(); //heap 메모리에 [증인, 토끼] 뜬다
u1.심문();
u2.대답();
}
}

판사와 증인이라는 추상메소드를 만들어서 다른 하위 클래스들를 상속 시킨다.
2. 새로운 증인 앨리스의 등장

앨리스 클래스를 만들었으나, 메소드 이름이 달라서 동적바인딩 실패! 작동 안함!!
3. 추상클래스, 추상메소드 (Abstract)
이 게임에서 실제로 존재하는 구체적인 것 (오브젝트) : 왕비, 토끼, 앨리스, 모자장수, 왕
아무 쓸모도 없고, heap도 못 띄우고, 존재하지도, 오브젝트도 아닌 것 : 판사, 증인
즉, '판사'와 '증인' 클래스가 추상클래스가 된다!! Abstract로 표시.

추상클래스와 추상메소드로 이루어진 모습

4. 추상적인 메소드 재정의 (Override)
<오류 발생!>

class 앨리스 extends 증인 {
public void 대답하다() {
System.out.println("앨리스는 대답한다");
}
}
>> 해당 코드는 오류 발생!!!!!!!

모자장수 클래스와 비교해보면, 메소드가 대답(), 대답하다()로 다르다. > 오류!!
<왜 그럴까?>
추상적인 메소드 재정의를 하지 않았기 때문.
추상클래스에선 '대답하다'라는 이름을 가진 메소드가 없음! > 에러
<메소드 재정의 (Override) 하는 법>


@Override를 사용해서 메서드의 이름, 타입, 매개변수 등을 강제한다.
: ‘동적바인딩’을 위해서.
개발자가 실수로 부모 클래스와의 메서드 이름, 매개변수, 반환 타입을
잘못 구현하는 것을 방지하기 위해 사용.
> 개발자의 실수를 방지하여 코드의 안정성을 높이는 역할
> 메서드 이름을 강제하는 것은 그 중 하나로,
올바른 메서드 재정의를 돕고 코드 품질을 향상 시키는데 도움
추상 메소드나 추상 클래스가 없어도 어노테이션을 사용할 수 있다.
ex) Lombok 라이브러리
전체 코드
package ex06.example5;
abstract class 판사 {
public abstract void 심문(); //껍데기만 만들기, 판사를 통로로만 사용
}
abstract class 증인 {
public abstract void 대답();
}
class 왕 extends 판사 {
public void 심문() {
System.out.println("왕은 심문한다");
}
}
class 왕비 extends 판사 {
public void 심문() {
System.out.println("왕비는 심문한다");
}
}
class 모자장수 extends 증인 {
public void 대답() {
System.out.println("모자장수는 대답한다");
}
}
class 토끼 extends 증인 {
public void 대답() {
System.out.println("토끼는 대답한다");
}
}
class 앨리스 extends 증인 {
public void 대답() {
System.out.println("앨리스는 대답한다");
}
}
public class AliceApp {
public static void main(String[] args) {
판사 u1 = new 왕비(); //메모리에 [판사, 왕비]
증인 u2 = new 토끼(); //메모리에 [증인, 토끼] 뜬다
증인 u3 = new 앨리스();
u1.심문();
u2.대답();
u3.대답();
}
}

Share article