5. 추상 클래스 & 추상 메소드 예시 - 이상한 나라의 앨리스
왕, 왕비 = 판사 / 모자장수, 토끼 = 증인
판사와 증인은 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