super를 사용함으로써 상속의 복잡도를 줄일 수 있는 대책을 알아보자.
아래예제는 기존에 있었던 예제입니다.
class Calculator{
int left,right;
public void setOperands(int left, int right) {
this.left=left;
this.right=right;
}
public void sum() {
System.out.println(this.left+this.right);
}
public void avg() {
System.out.println((this.left+this.right)/2);
}
}
class SubstractionableCalculator extends Calculator{
public SubstractionableCalculator(int left, int right) {
this.left=left;
this.right=right;
}
public void substract() {
System.out.println((this.left)-(this.right));
}
}
public class CalculatorSuper2{
public static void main(String[] args) {
//SubstractionableCalculator의 생성자 c1호출하여 left,right값을 받아옴
SubstractionableCalculator c1=new SubstractionableCalculator(10,20);
c1.sum();
c1.avg();
c1.substract();
}
}
만약 클래스 Calculaotr가 메소드 Operands가 아니라 생성자를 통해서 left,right값을 설정하고 싶다면 아래와 같이 Calculator생성자를 호출해줍니다.
class Calculator{
int left,right;
//메소드 Calculator호출
public Calculator(int left, int right){
this.left = left;
this.right = right;
}
public void setOperands(int left, int right) {
this.left=left;
this.right=right;
}
public void sum() {
System.out.println(this.left+this.right);
}
public void avg() {
System.out.println((this.left+this.right)/2);
}
}
실행결과는 '상위클래스인 Calculator의 생성자가 존재하지 않는다'라는 오류 메세지가 발생하게 됩니다. 이를 해결하기 위해서는 상위클래스에 기본생성자를 추가하면 됩니다.
class Calculator{
int left,right;
//상위클래스인 Calculator의 기본생성자 추가
//자바에서는 상위클래스에 매개변수가 있는 생성자가 있다면
//자동으로 상위클래스의 기본생성자를 만들어주지 않음
public Calculator() {
}
//만약 클래스Calculator가 메소드 setOperands가 아니라 생성자를 통해서 left,right값을
//설정하도록 하고 싶다면 메소드 Calculator호출한다.
public Calculator(int left,int right) {
this.left=left;
this.right=right;
}
public void setOperands(int left, int right) {
this.left=left;
this.right=right;
}
public void sum() {
System.out.println(this.left+this.right);
}
public void avg() {
System.out.println((this.left+this.right)/2);
}
}
class SubstractionableCalculator extends Calculator{
public SubstractionableCalculator(int left, int right) {
this.left=left;
this.right=right;
}
public void substract() {
System.out.println((this.left)-(this.right));
}
}
public class CalculatorSuper{
public static void main(String[] args) {
//SubstractionableCalculator의 생성자 c1호출
SubstractionableCalculator c1=new SubstractionableCalculator(10,20);
c1.sum();
c1.avg();
c1.substract();
}
}
그런데 상위클래스인 Calculator에는 left와 right값을 초기화할 수 있는 좋은 생성자가 이미 존재합니다. 이것을 사용한다면 하위 클래스에서 left,right값을 직접 설정하는 불필요한 절차를 생략할 수 있을 것입니다. 어떻게 하면 상위클래스의 생성자를 호출할 수 있을까?
class Calculator{
int left,right;
//부모클래스의 기본생성자가 없어져도 오류발생안함
public Calculator(int left,int right) {
this.left=left;
this.right=right;
}
public void setOperands(int left, int right) {
this.left=left;
this.right=right;
}
public void sum() {
System.out.println(this.left+this.right);
}
public void avg() {
System.out.println((this.left+this.right)/2);
}
}
class SubstractionableCalculator extends Calculator{
public SubstractionableCalculator(int left, int right) {
//super()객체 생성자를 이용해 부모클래스의 생성자 left,right를 호출합니다.
super(left,right);
}
public void substract() {
System.out.println((this.left)-(this.right));
}
}
public class CalculatorSuper{
public static void main(String[] args) {
//SubstractionableCalculator의 생성자 c1호출
SubstractionableCalculator c1=new SubstractionableCalculator(10,20);
c1.sum();
c1.avg();
c1.substract();
}
}
위와 같이 super함수를 추가하면 부모클래스의 기본생성자가 없어져도 오류가 발생하지 않습니다.
하위클래스의 생성자에서 super를 사용할 때 주의할 점은 super가 가장 먼저 나타나야한다는 것입니다. 즉 부모가 초기화되기 전에 자식이 초기화되는 일을 방지하기 위한 정책이라고 생각하면 됩니다.
super란 자식클래스에서 상속받은 부모클래스의 멤버변수를 참조할 때 사용합니다.
super()는 자식클래스가 자신을 생성할 때 부모 클래스의 생성자를 불러 초기화 할때 사용됩니다.
1) 제가 알기론, 객체생성 시 기본생성자가 무조건 자동으로 한 번 돌거에요. 생성자 선언을 하지 않았다면, 입출력 없는 녀석이 돌구요.
setOperands는 따로 선언한 일반함수로 보이는데, 이 경우 Calculator C1 = new setOperands(0,0) 은 컴파일 에러가 나야 되는거 아닌가요?
이게 된다면 setOperands 라는 것이 모든 객체 생성에 사용되는 일종의 약속이라고 봐야겠네요.
2)
"만약 클래스 Calculaotr가 메소드 Operands가 아니라 생성자를 통해서 left,right값을 설정하고 싶다면 아래와 같이 Calculator생성자를 호출해줍니다."
이 말이 참 애매합니다. 생성자로 초기화 안할거면, 초기화 기능이 없는 생성자로 객체를 생성한 후에,
일반 함수인 Operands로 초기화 하라는 말인가요?
3) 보통 상속이 없는 클래스는 객체생성 시 기본 생성자가 자동으로 생성되는 걸로 보이는데,
상속을 사용할 경우 부모 클래스의 생성자는 따로 선언을 해주어야 하네요.
그냥 코딩 할 때, 생성자 선언하는 것을 습관화 하는게 좋아보여요.
4) 기본생성자는 입출력이 없는 녀석인가봐요. 같은 이름에 입출력이 있는 녀석은 일반 생성자라고 보면 될거같네요.
상속을 보니까, 기본생성자의 의미가 크게 느껴져요. 자식 클래스에서 부모 클래스의 변수에 접근하기 전에, super()를 쓰지 않는다면 부모 클래스의 기본생성자를 따로 선언해줘야 하니까요.
super()도 결국 편의기능이니까, 가급적이면, 부모 클래스에 기본생성자를 만드는 쪽으로 먼저 연습하는게 좋겠어요.