자바 추상 클래스
객체 지향 개념에서 모든 객체는 클래스로 설명되지만, 반대로 모든 클래스가 객체를 설명하는 데 사용되는 것은 아닙니다. 클래스에 콘크리트 객체를 설명할 만큼 충분한 정보가 포함되어 있지 않으면 이러한 클래스는 추상 클래스입니다.
추상 클래스가 객체를 인스턴스화할 수 없다는 점을 제외하면 클래스의 다른 함수는 여전히 존재합니다. 멤버 변수, 멤버 메서드 및 생성자는 일반 클래스와 동일한 방식으로 액세스할 수 있습니다.
추상 클래스는 객체를 인스턴스화할 수 없으므로 추상 클래스를 사용하려면 먼저 상속받아야 합니다. 이러한 이유로 추상 클래스를 디자인할지 여부는 일반적으로 디자인 단계에서 결정됩니다.
상위 클래스에는 하위 클래스 컬렉션에 대한 공통 메서드가 포함되어 있지만 상위 클래스 자체가 추상이므로 이러한 메서드를 사용할 수 없습니다.
추상 클래스
추상 클래스를 정의하려면 Java 언어의 추상 클래스를 사용하세요. 다음 예:
/* 文件名 : Employee.java */ public abstract class Employee { private String name; private String address; private int number; public Employee(String name, String address, int number) { System.out.println("Constructing an Employee"); this.name = name; this.address = address; this.number = number; } public double computePay() { System.out.println("Inside Employee computePay"); return 0.0; } public void mailCheck() { System.out.println("Mailing a check to " + this.name + " " + this.address); } public String toString() { return name + " " + address + " " + number; } public String getName() { return name; } public String getAddress() { return address; } public void setAddress(String newAddress) { address = newAddress; } public int getNumber() { return number; } }
Employee 클래스도 다르지 않습니다. 클래스는 추상 클래스이지만 여전히 3개의 멤버 변수, 7개의 멤버 메서드 및 1개의 생성자가 있습니다. 이제 다음 예제를 시도하면:
/* 文件名 : AbstractDemo.java */ public class AbstractDemo { public static void main(String [] args) { /* 以下是不允许的,会引发错误 */ Employee e = new Employee("George W.", "Houston, TX", 43); System.out.println("\n Call mailCheck using Employee reference--"); e.mailCheck(); } }
AbstractDemo 클래스를 컴파일하려고 하면 다음 오류가 생성됩니다.
Employee.java:46: Employee is abstract; cannot be instantiated Employee e = new Employee("George W.", "Houston, TX", 43); ^ 1 error
Inheriting abstract class
일반적인 방법을 통해 Employee 클래스를 상속할 수 있습니다.
/* 文件名 : Salary.java */ public class Salary extends Employee { private double salary; //Annual salary public Salary(String name, String address, int number, double salary) { super(name, address, number); setSalary(salary); } public void mailCheck() { System.out.println("Within mailCheck of Salary class "); System.out.println("Mailing check to " + getName() + " with salary " + salary); } public double getSalary() { return salary; } public void setSalary(double newSalary) { if(newSalary >= 0.0) { salary = newSalary; } } public double computePay() { System.out.println("Computing salary pay for " + getName()); return salary/52; } }
인스턴스화할 수는 없지만 Employee 클래스의 객체를 인스턴스화합니다. 하지만 Salary 클래스 객체를 인스턴스화하면 해당 객체는 Employee 클래스로부터 3개의 멤버 변수와 7개의 멤버 메소드를 상속받게 됩니다.
/* 文件名 : AbstractDemo.java */ public class AbstractDemo { public static void main(String [] args) { Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00); Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00); System.out.println("Call mailCheck using Salary reference --"); s.mailCheck(); System.out.println("\n Call mailCheck using Employee reference--"); e.mailCheck(); } }
위 프로그램을 컴파일하고 실행한 결과는 다음과 같습니다.
Constructing an Employee Constructing an Employee Call mailCheck using Salary reference -- Within mailCheck of Salary class Mailing check to Mohd Mohtashim with salary 3600.0 Call mailCheck using Employee reference-- Within mailCheck of Salary class Mailing check to John Adams with salary 2400.
추상 메소드
특수 멤버 메소드가 포함된 이러한 클래스를 설계하려는 경우 메소드의 구체적인 구현은 다음에 의해 결정됩니다. 하위 클래스인 경우 해당 메서드를 상위 클래스의 추상 메서드로 선언할 수 있습니다.
추상 키워드는 추상 메서드를 선언하는 데에도 사용할 수 있습니다. 추상 메서드에는 메서드 이름만 포함되고 메서드 본문은 포함되지 않습니다.
추상 메서드는 정의되지 않았으며, 메서드 이름 바로 뒤에 중괄호 대신 세미콜론이 옵니다.
public abstract class Employee { private String name; private String address; private int number; public abstract double computePay(); //其余代码 }
추상 메서드를 선언하면 다음 두 가지 결과가 발생합니다.
클래스에 추상 메소드가 포함되어 있으면 클래스는 추상이어야 합니다.
모든 하위 클래스는 상위 클래스의 추상 메서드를 재정의하거나 자신을 추상 클래스로 선언해야 합니다.
추상 메서드를 상속하는 하위 클래스는 이 메서드를 재정의해야 합니다. 그렇지 않으면 서브클래스도 abstract로 선언되어야 합니다. 결국 하위 클래스는 추상 메서드를 구현해야 합니다. 그렇지 않으면 초기 상위 클래스나 최종 하위 클래스를 사용하여 객체를 인스턴스화할 수 없습니다.
Salary 클래스가 Employee 클래스를 상속하는 경우 ComputePay() 메서드를 구현해야 합니다.
/* 文件名 : Salary.java */ public class Salary extends Employee { private double salary; // Annual salary public double computePay() { System.out.println("Computing salary pay for " + getName()); return salary/52; } //其余代码 }