오늘 포스팅 할 내용은 자바 자체를 이해하는데 아주 중요한 내용이다. 내가 느끼기엔 다소 어려운 내용이었기 때문에 최대한 모든 글자를 하나하나 다 읽고 포스팅한 흐름대로 이해해야 한다.
1 상속과 생성자
자손클래스의 생성자 작업을 할 때 부모 클래스의 생성자도 반드시 호출해주어야 한다. 만약 자식클래스의 생성자 내부에 부모클래스의 생성자를 따로 호출하지 않았다면 자동적으로 컴파일러는 부모클래스에 기본생성자를 호출하거나 예외적인 경우 오류를 발생하기도 하기 때문이다.
위의 내용을 자세하게 이해하기 위해 생성자에 대해 더 깊게 공부해보자.
아래 포스팅을 참고하면 아래 내용이 더 잘 눈에 들어올 것이다.
생성자의 구조는 다음과 같다.
class 클래스명 {
클래스명(){ } // '기본 생성자'
}
class 클래스명 {
클래스명(매개변수){ } // '매개변수를 갖는 생성자'
}
기본생성자와 매개변수를 갖는 생성자가 있다.
Constructor 클래스 생성후 c1이라는 객체를 매개변수 없이 생성해 주었다.
class Constructor{
}
public class Extends_Constructor {
public static void main(String[] args) {
Constructor1 c1 = new Constructor1();
}
}
// 위 예제는 에러없이 작동한다. 매개변수가 없는 c1객체 생성시에 컴파일러가 자동으로 Constructor 클래스 내부에 매개변수가 없는 기본생성자를 만들어주기 때문이다.
아래 그림과 같이 생성자 "Constructor(){}" 를 class에 자동으로 만들어준다.
다음은 매개변수를 갖는 생성자를 만들어준 모습이다. (볼드체 부분이 추가해준 부분.)
class Constructor{
Constructor(int a){} // 매개변수를 갖는 생성자 (기본 생성자 아님)
}
public class Extends_Constructor {
public static void main(String[] args) {
Constructor1 c1 = new Constructor1(); // ⓧ
}
}
// 에러가 발생한다. Constructor 생성자에 매개변수가 존재한다는 것은 기본 생성자가 아니다. 또한 매개변수가 없는 생성자(기본 생성자)가 존재하지 않기 때문에 매개변수가 없는 인스턴스 c1객체 생성시 오류가 발생하게 되는것이다.
따라서 자바는 생성자가 존재 할 경우 기본 생성자를 만들어 주지 않는다는 것을 알 수 있다.
위 코드를 오류가 발생하지 않도록 하기 위해서 매개변수를 갖지 않는 생성자를 추가해 주어야한다. (볼드체 부분이 추가해준 부분.)
class Constructor{
Constructor(){}
Constructor(int a){}
}
public class Extends_Constructor {
public static void main(String[] args) {
Constructor1 c1 = new Constructor1();
}
}
// 이처럼 매개변수가 없는 기본생성자를 명시적으로 선언해주면 매개변수가 없는 인스턴스 객체 생성시 오류가 발생하지 않게 된다.
이번에는 상속된 클래스를 예로 들어보자.
다음 Calculator1을 상속한 자식 클래스 SubstractionableCalculator를 호출하는 예제이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package java_practice;
class Calculator1 { int left, right;
public void setOprands(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 Calculator1 { public SubstractionableCalculator(int left, int right) { this.left = left; this.right = right; }
public void substract() { System.out.println(this.left - this.right); } }
public class Sanghwoal { public static void main(String[] args) { SubstractionableCalculator c1 = new SubstractionableCalculator(10, 20); c1.sum(); c1.avg(); c1.substract(); } } |
cs |
줄 33에서 자식클래스의 인스턴스 객체 생성시 매개변수를 입력해주었다. 따라서 입력한 10,과 22는 줄21의 자식클래스의 생성자 int left, int right 안에 각각 들어갈 것이고, SubstractionableCalculator 의 부모 클래스 Calculator1 은 클래스 내부에 생성자가 따로 없기 때문에 컴파일러가 기본 생성자를 자동으로 만들어주어 위 코드는 에러없이 작동 될 것이다.
하지만 만약 줄33에서 객체 생성시에 매개변수를 입력하지 않는다면
(
SubstractionableCalculator c1 = new SubstractionableCalculator();
)
SubstractionableCalculator 클래스는 기본생성자가 존재하지 않기 때문에 에러가 발생한다.
따라서 매개변수를 입력하지 않을 경우 다음과 같이 줄21에 기본생성자를 추가해 주어야한다. (볼드체 부분이 추가해준 부분.)
class SubstractionableCalculator extends Calculator1 {
public SubstractionableCalculator() {}
.
.
.
다음 부모클래스 Calculator1에 매개변수를 갖는 생성자를 추가해주었다. (볼드체 부분이 추가해준 부분.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
package java_practice;
class Calculator1 { int left, right;
public Calculator1(int left, int right){ this.left = left; this.right = right; }
public void setOprands(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 Calculator1 { public SubstractionableCalculator(int left, int right) { // ⓧError! this.left = left; this.right = right; }
public void substract() { System.out.println(this.left - this.right); } }
public class Sanghwoal { public static void main(String[] args) { SubstractionableCalculator c1 = new SubstractionableCalculator(10,20); c1.sum(); c1.avg(); c1.substract(); } } |
cs |
다음과 같이 코드 작성시 줄26에서 아래의 에러가 발생할 것이다. Implicit super constructor Calculator1() is undefined. Must explicitly invoke another constructor
줄38에 SubstractionableCalculator 객체가 생성 될 때, 줄25의 생성자가 호출되게 되고 이 클래스의 부모클래스인 줄3 Calculator1에 기본생성자 또한 호출되어야 하는데 Calculator1은 이미 기본 생성자가 아닌 줄 6에 매개변수를 갖는 생성자를 갖고 있기 때문에 줄26에 에러 메세지가 뜨게 되는것이다.
따라서 줄5에 다음과 같이 기본생성자를 정의해주면 된다. (볼드체 부분이 추가해준 부분.)
class Calculator1 {
int left, right;
public Calculator1(){ }
public Calculator1(int left, int right){
this.left = left;
this.right = right;
}
}
하지만 위처럼 기본생성자를 따로 정의해주지 않고도 에러가 발생되지 않도록 하는 방법이 있다.
위 코드의 줄7~8과 줄 27~28은 중복이다. 상위 클래스의 생성자와 하위 클래스의 생성자의 코드가 같을 때 사용하는 코드인 super();를 사용해 주는 것이다.
위의 코드를 super를 이용해 줄27~28을 다음과 같이 고칠 수 있다. (볼드체 부분이 바뀐 부분.)
public SubstractionableCalculator(int left, int right) {
super(left,right);
}
super는 부모클래스를 의미한다. 마치 this가 자기자신을 의미하는 것과 비슷한 맥락이다. 따라서 "super()" = "부모클래스()"로 생성자라는 뜻이다.
따라서 SubstractionableCalculator(int left, int right)의 int left, int right가 각각 super(left,right); 안의 left,right 값으로 들어가고 이 left와 right 값은 부모 클래스의 생성자인 Calculator1(int left, int right)의 left,right 값으로 들어가게 되는 것이다.
또한 Calculator1의 생성자 호출 후 SubstractionableCalculator 의 생성자 내부에서 뭔가더 실행시키고 싶은 로직이 있다면 super();를 호출한 다음에 나타나야한다.
이는 상위 클래스의 초기화가 다 끝낸 상태에서 하위클래스의 초기화를 진행할 수 있기 때문이다.
★[정리]
- this : "객 체 자 기 자 신"(의 참조값)
- this() : 생성자 첫째줄에서 또다른 생성자를 호출.
- super : 부모클래스의 객체(의 참조값)
- super() : 생성자 첫째줄에서 부모클래스의 생성자를 호출.
'Java > Java 기초문법' 카테고리의 다른 글
[JAVA 기초] 자바 package와 import (0) | 2021.03.11 |
---|---|
[JAVA 기초] 자바 오버라이딩(Overriding) (0) | 2021.03.11 |
[JAVA 기초] 자바 클래스 - 상속(Extends) (0) | 2021.03.11 |
[JAVA 기초] .java 파일 클래스 분리 (Refactor) (0) | 2021.03.11 |
[JAVA 기초] 자바 오버로딩, 생성자 (0) | 2021.03.10 |
댓글