상속이 있는 Subclass의 Constructor 호출 및 실행 과정에 대해서 알아보려 합니다.
/* 코드 출처는 H. M. Deitel, P. J. Deitel , Java How to Program (Early Objects),
Global Edition, 11th Edition, Pearson임을 밝힙니다. */
// Fig. 9.7: BasePlusCommissionEmployeeTest.java
// BasePlusCommissionEmployee test program.
public class BasePlusCommissionEmployeeTest {
public static void main(String[] args) {
// instantiate BasePlusCommissionEmployee object
BasePlusCommissionEmployee employee =
new BasePlusCommissionEmployee(
"Bob", "Lewis", "333-33-3333", 5000, .04, 300);
}
}
위와같이, Driver class인 BasePlusCommissionEmployeeTest를 실행시켰다고 해봅시다.
그러면 가장 먼저 new 키워드를 통해, BasePlusCommissionEmployee의 employee 라는 객체가 하나 생성됩니다.
모든 객체는 생성될때, 가장 먼저 자기 자신의 클래스의 Constructor를 호출하게 되어있습니다.
// Fig. 9.11: BasePlusCommissionEmployee.java
// BasePlusCommissionEmployee class inherits from CommissionEmployee
public class BasePlusCommissionEmployee extends CommissionEmployee {
// six-argument constructor
public BasePlusCommissionEmployee(String firstName, String lastName,
String socialSecurityNumber, double grossSales,
double commissionRate, double baseSalary) {
super(firstName, lastName, socialSecurityNumber,
grossSales, commissionRate); // 부모 클래스의 Constructor 호출
this.baseSalary = baseSalary;
}
}
코드에서 public BaseplusCommissionEmployee()에 해당 하는 부분이 바로 객체가 생성될때,
가장 먼저 호출되는 Constructor 입니다.
그리고 현재 BaseplusCommissionEmployee라는 클래스는, extends 키워드를 통해
CommissionEmployee으로부터 상속된 Subclass입니다.
모든 Subclass의 constructor가 호출될떄, 가장 먼저 하는 일은 바로 자기 자신의 Superclass의 constructor를 호출하는 일입니다.
위 코드에서는 super() 이라는 메소드를 통해 CommissionEmployeed의 constructor을 explicitiy하게 호출하고 있습니다.
// Fig. 9.10: CommissionEmployee.java
public class CommissionEmployee {
private final String firstName;
private final String lastName;
private final String socialSecurityNumber;
private double grossSales; // gross weekly sales
private double commissionRate; // commission percentage
// five-argument constructor
public CommissionEmployee(String firstName, String lastName,
String socialSecurityNumber, double grossSales,
double commissionRate) {
// implicit call to Object constructor occurs here
// super() 이 생략되어있음
this.firstName = firstName;
this.lastName = lastName;
this.socialSecurityNumber = socialSecurityNumber;
this.grossSales = grossSales;
this.commissionRate = commissionRate;
}
}
super() 메소드를 통해, 우리는 위와같은 CommissionEmployee의 Constructor를 호출한것입니다.
그리고, CommissionEmployee의 Constructor 또한 최상위 클래스인 Object의 Subclass이기 때문에
자신의 Superclass인 Object 클래스의 Constructor 을 호출합니다.
이러한 과정을 Chain of construtor call 이라고 합니다. 꼬리에 꼬리를 무는 형식이죠.
여기서는 위와는 다르게, super() 메소드가 생략되어 Superclass의 Constructor을 implicity하게 호출하고 있습니다.
만약, 이와같이 super() 메소드를 이용하지않고 Constructor을 implicity하게 호출하는 경우에는
Java에서 자동으로 Superclass의 default or no-argument constructor을 호출하게 되어있습니다.
위 코드에서는, Object 클래스에 default constructor가 잘 정의되어 있기때문에, 에러없이 계속해서 잘 실행되게 됩니다.
public class Object {
/**
* Constructs a new object.
*/
public Object() {} // 잘 정의되어 있는 default constructor
}
정리하자면, 다음과 같습니다.
① new 키워드를 이용해 BaseplusCommissionEmployee 클래스의 employee 객체를 생성.
② employee 객체가 생성될 때, 가장 먼저 하는 일은 자신의 클래스인
BaseplusCommissionEmployee의 Constructor을 호출.
③ BaseplusCommissionEmployee Constructor가 CommissionEmployee의 Constructor을 호출.
④ CommissionEmployee의 Constructor가 Object의 Constructor을 호출.
여기서, 추가적으로 조금 더 생각해봅시다.
④번 과정에서, 우리는 super() 메소드를 생략할 수 있었습니다.
그렇다면 만약에, ③번 과정에서 super(...) 메소드를 생략하면 어떻게 될까요?
// Fig. 9.11: BasePlusCommissionEmployee.java
// BasePlusCommissionEmployee class inherits from CommissionEmployee
public class BasePlusCommissionEmployee extends CommissionEmployee {
// six-argument constructor
public BasePlusCommissionEmployee(String firstName, String lastName,
String socialSecurityNumber, double grossSales,
double commissionRate, double baseSalary) {
super(firstName, lastName, socialSecurityNumber,
grossSales, commissionRate); // 이 구문을 생략한다면..?
this.baseSalary = baseSalary;
}
}
이때는, 컴파일 에러가 발생합니다.
그 이유는 ③번 과정에서, CommissionEmployee 클래스에는 이미 매개변수가 5개나 있는 constructor가 정의되어 있기 때문입니다.
앞서 설명했듯이, super() 메소드는 자신의 Superclass의 default or no-argument constructor을 호출하게 되어있습니다.
그런데 이미 CommissionEmployee 클래스에는 default or no-argument constructor가 아닌,
매개변수가 5개나 있는 Constructor가 잘 정의되어 있기 때문에 컴파일 단계에서 에러가 발생하는 것입니다.
따라서, 자신의 Superclass의 construtor의 매개변수가 하나이상이라도 있다면 우리는 반드시 super() 메소드를 통해
Superclass의 construtor을 explicitiy하게 호출하여야 합니다.