생성자(Constructor)는 특정 객체를 기준으로 해당 클래스의 비정적(non-static) 멤버들을 초기화하는 역할을 합니다. 그렇다면 왜 자바에서는 추상 클래스에는 생성자가 존재하지만, 인터페이스에는 생성자가 없을까요? 각각의 이유를 예제 코드와 함께 살펴보겠습니다.
인터페이스에 생성자가 없는 이유
- 자바의 인터페이스(Interface)에는 생성자가 없습니다. 그 이유는 인터페이스의 모든 데이터 멤버가 기본적으로 public static final로 선언되는 상수(constant)이기 때문입니다. 상수는 선언 시점에 값을 할당해야 하므로 생성자를 통한 초기화 과정이 필요하지 않습니다.
- 인터페이스에는 생성자로 초기화할 수 있는 일반적인 인스턴스 변수 자체가 존재하지 않습니다.
- 메서드를 호출하려면 객체가 필요한데, 인터페이스의 메서드는 구현부(메서드 바디)가 없으므로 직접 호출할 대상이 없습니다.
- 결국 인터페이스의 메서드를 직접 호출할 수 없기 때문에 인터페이스의 객체를 생성할 필요가 없고, 따라서 생성자도 필요하지 않습니다.
예제 1
interface Addition {
int add(int i, int j);
}
public class Test implements Addition {
public int add(int i, int j) {
int k = i+j;
return k;
}
public static void main(String args[]) {
Test t = new Test();
System.out.println("k value is:" + t.add(10,20));
}
}
출력 결과
k value is:30
위 예제처럼 인터페이스는 구현 클래스(Test)를 통해 객체를 생성하고 메서드를 사용합니다. 인터페이스 자체를 객체화하는 것은 불가능합니다.
클래스(추상 클래스)의 생성자
- 클래스에서 생성자의 목적은 필드를 초기화하는 것이지, 객체를 생성(빌드)하는 것이 아닙니다.
- 추상 슈퍼클래스의 새 인스턴스를 직접 생성하려고 하면 컴파일러가 오류를 발생시킵니다.
- 그러나 추상 클래스를 상속한 서브클래스에서는
super()키워드를 통해 부모 클래스의 생성자를 호출하여 변수를 설정할 수 있습니다.
예제 2
abstract class Employee {
public String empName;
abstract double calcSalary();
Employee(String name) {
this.empName = name; // 추상 클래스의 생성자
}
}
class Manager extends Employee {
Manager(String name) {
super(name); // 서브클래스의 생성자에서 이름 설정
}
double calcSalary() {
return 50000;
}
}
public class Test {
public static void main(String args[]) {
Employee e = new Manager("Adithya");
System.out.println("Manager Name is:" + e.empName);
System.out.println("Salary is:" + e.calcSalary());
}
}
출력 결과
Manager Name is:Adithya Salary is:50000.0
정리
요약하자면, 인터페이스는 오직 상수와 추상 메서드만 가지며 객체화될 수 없기 때문에 생성자가 필요 없습니다. 반면 추상 클래스는 인스턴스 변수를 가질 수 있고, 서브클래스가 super()를 통해 이를 초기화할 수 있어야 하므로 생성자를 가질 수 있습니다. 즉, 추상 클래스의 생성자는 직접적인 객체 생성이 아니라 상속 구조에서 공통 필드를 초기화하기 위한 용도로 사용됩니다.