abstract class Parent2 {
void viewData1() {
System.out.println("Parent2 viewData1() 호출"); // 일반 메서드
}
abstract void viewData2(); // 추상 메서드
}
abstract class Parent {
abstract void method1();
}
abstract class Child extends Parent {
// 추상 메서드를 구현하지 않으면 이 클래스도 추상 클래스가 됨
}
class GrandChild extends Child {
// 오버라이딩하여 추상 메서드를 구현
void method1() {
System.out.println("GrandChild method1 호출");
}
}
즉, 추상 클래스는 구체적인 구현이 자식 클래스에서 완성되므로, 객체화하려면 자식 클래스에서 추상 메서드를 반드시 구현해야 한다.
abstract class Parent2 {
Parent2() {
System.out.println("Parent2 생성자 호출");
}
void viewData1() {
System.out.println("Parent2 viewData1() 호출"); // 일반 메서드
}
abstract void viewData2(); // 추상 메서드
}
class Child2 extends Parent2 {
Child2() {
System.out.println("Child2 생성자 호출");
}
@Override
void viewData2() {
System.out.println("Child2 viewData2() 호출");
}
}
public class AbstractMainEx01 {
public static void main(String[] args) {
// Parent2 p2 = new Parent2(); // 추상 클래스는 객체화 불가
Child2 c2 = new Child2(); // 자식 클래스는 객체 생성 가능
c2.viewData1(); // 상속받은 일반 메서드 호출
c2.viewData2(); // 자식 클래스에서 오버라이딩된 추상 메서드 호출
}
}
- 추상 메서드는 구체적인 구현이 없는 메서드로, 자식 클래스에서 구현을 강제한다.
- 추상 클래스는 불완전한 클래스로, 구현되지 않은 추상 메서드를 포함할 수 있으며, 객체 생성이 불가능하다.
- 추상 클래스를 상속받은 자식 클래스는 추상 메서드를 반드시 구현해야 하며, 그렇지 않으면 그 자식 클래스도 추상 클래스가 된다.
- 추상 클래스는 공통된 필드와 메서드를 정의하고, 자식 클래스에서 구현해야 할 부분만 추상 메서드로 선언하여 상속을 통한 코드 재사용성과 유지보수성을 높인다.