참조변수 super, 생성자 super()
참조변수 super
- 객체 자신을 가리키는 참조변수, 인스턴스 메서드(생성자)내에만 존재
- 조상의 멤버를 자신의 멤버와 구별할 때 사용
참조변수 super는 객체 자신을 가리키는 참조변수이다. this와 거의 같다고 보면 된다.
this도 인스턴스 메서드 내에서만 사용할 수 있다. static메서드에서는 사용 할 수 없다.
this는 lv와 iv구별에 사용했다.
super는 조상의 멤버와 자신의 멤버를 구별할 때 사용한다.
코드를 보면, Parent클래스가 있고, Child클래스가 있다.
Child클래스는 Parent클래스의 자식이다. 그런데, Parent클래스에도 x가 있고, Child클래스에도 x가 있다. 두클래스에 x가 있는 것이 가능하다.
Child객체를 만들면, 참조변수 c를 만들고 멤버가 자신의 멤버 + 상속받은 멤버 해서 총 3개이다.
x, x, method() 3개의 멤버가 있다.
x가 2개인데, 하나는 조상꺼, 하나는 자기꺼다.
그래서 조상의 X는 super.x이고, 자신의 x는 this.x이다.
그런데, 초기화가 각가 10,. 20으로 되었고 그림으로 표현하면 위와 같다.
이름이 같아도, 하나씩 따로 만들어진다. x가 2개다. 구별은 super.x 그리고 this.x로 구별된다.
그래서 c.method()호출하면 참조변수 c가 가리키는 객체의 메서드 호출하면 문장들이 실행된다.
첫번째 Sytem.out.println("x=" +x)에서 x는 가까운쪽에 있는 this.x이다. 그래서 20이다.
두번째 System.out.println("this.x=" + this.x);의 this.x는 위와 동일한 20이다.
세번째 System.out.println("super.x="+super.x); 의 super.x는 10이다.
이 예제에서 중요한 것은, 이름이 겹칠 때도 상속이 되고, 둘다 존재한다.
구별은 super와 this로 구별한다.
이번에는 예제 7_3이다.
이번에는 앞의 예제와 다 똑같은데, 단, 자손클래스에 x가 없다.
그리고 조상에만 x가 있다.
이번경우에는 중복된 멤버(x)가 없는 경우이다.
그런 경우에 Child2객체를 생성하면 어떻게 될까?
참조변수 c를 만들고, 멤버가 1 + 1로 총 2개가 있다. x와 method().
그리고 x는 10으로 초기화 될 것이다.
근데 이때 x는 조상의 X이다. 자손클래스 자신에게는 x가 없었으니까 말이다.
결국, this.x도 조상의 x고, super.xㄷ 조상의 x 이다.
x가 하나밖에 없기 때문이다. 그래서 다 10이 나온다.
조상멤버기도 하지만, 자신의 것이기도 하니까 super.x, this.x 둘 다 가능하다.
super() - 조상의 생성자
- 조상의 생성자를 호출할 떄 사용
- 조상의 멤버는 조상의 생성자를 호출해서 초기화
이것도 참조변수 super와 연관지으면 안된다. 전혀 연관없다.
super()는 생성자이다.
언제사용하냐면, 조상의 생성자를 호출할 때 사용한다.
조상의 생성자를 호출할 일이 있을까? 있다. 자손클래스의 생성자에서 조상클래스의 생성자를 호출 할 때가 있다.
상속의 개념에서 기억해야 할 것은 생성자와 초기화 블럭은 상속이 안된다는 것이다.
조상의 멤버는 조상의 생성자를 호출해서 초기화를 해야 한다.
코드를 살펴보자.
좌측에는 Point클래스와 x,y가 있다.
우측에는 Point를 상속받은 Point3D클래스가 있다. 그리고 int z가 추가되었다.
Point에서는 x, y (iv)를 초기화 한다.
Point3D에서도 iv초기화를 한다. 그런데, x와 y는 조상의 멤버다.
조상의 멤버인데 Point3D클래스의 생성자 즉, 자손의 생성자가 조상의 멤버를 초기화하고있다.
에러는 아니지만, 이렇게 하면 안된다.
자손의 생성자는 자기가 선언한 것만 초기화 해야한다.
그래서 우측의 코드를 아래와 같이 바꿔야 한다.
조상의 멤버를 자신이 초기화하지 않고, 조상의 생성자를 호출하는 것이다.
왜냐하면, 조상의 멤버를 어떻게 초기화해야할 지 제일 잘 아는 것은 조상이기 때문이다.
super(x, y )처럼 클래스이름을 쓰지 않고 super를 사용하는 것이다. 이것이 의미하는 것은 Point(int x, int y)를 호출하는 것이다.
정리하면, super()는 조상의 생성자인데, 자손 클래스에서 조상 생성자를 호출할 때는 super()를 쓴다.
super()를 왜쓰냐면, 조상이 선언한 멤버를 초기화 하려면 내가 직접할게 아니라, 조상의 생성자를 호출해서 조상의 생성자가 조상멤버를 초기화하도록 해야한다.
매우 중요한 개념
생성자의 추가조건인데,
생성자의 첫 줄에 반드시 생성자를 호출해야 한다. (super(), this())
그렇지 않으면, 컴파일러가 생성자의 첫 줄에 super();를 삽입한다.
좌측 코드에서 Point() 생성자는 첫 줄이 this(0, 0) 호출했으므로 OK,
그런데, 두번째 Point(int x , int y)에서는 첫번째 줄이 생성자 호출이 아니므로 컴파일을 하면,
우측과 같이 코드가 변경된다. Point클래스의 최고조상이 Object클래스 이므로,
super();가 결국 object();와 동일한 의미가 된다.
예제를 통해서 확인해 보자. (중요 예제)
여기서 main메서드에서 Point3D객체를 생성한다. 그런데 이것을 컴파일 하면 에러가 난다.
Point()라는 생성자가 없어서 난 에러이다.
"Point3D객체를 만드는데 왠 Point()생성자가 없다고 나오지?"
그리고 에러 발생 위치가 Point3D(int x, int y, int z) 즉, Point3D생성자를 호출하는데서 에러가 발생했다.
왜 에러가 났을까? 생각을 해보자.
방금전에 공부한 조건
생성자의 첫 줄에 반드시 다른 생성자를 호출해야 한다.
그렇지 않으면, 컴파일러가 생성자의 첫 줄에 super();를 삽입한다.
그래서 Point(int x, int y)를 보면, 첫번쨰 줄에서 생성자 호출을 하지 않는다.
그러면 컴파일을하면 코드가 super(); 를 자동으로 추가하게 된다.
왜냐하면, 모든 생성자는 첫줄에 반드시 다른 생성자를 호출해야하는데, 그렇지 않았기 때문이다.
그래서 규칙에 따라 컴파일러가 넣어준 것이다.
super();의 의미는 Point의 조상인 Object클래스의 생성자이다.
그리고 아래에 Point3D클래스의 생성자도 첫번쨰 줄에서 생성자 호출을 하지 않았다.
그래서 super();가 자동으로 추가 되게 된다.
여기서 super()의 의미는 Point3D의 조상 Point()생성자이다.
그래서 에러가 낫던 구문을 다시 살펴보면,
Point3D p3 = new Point3D(1, 2, 3);
이 부분에서 (1, 2, 3)이 넘어가는데 super()를 호출하므로 조상인 Point클래스의 기본 생성자 Point()생성자를 호출하는데,
Point클래스의 Point(int x, int y)에는 point(){}가 없다.
왜냐하면
여기에 이렇게 생성자가 있기 때문에,
컴파일러가 기본 생성자를 자동으로 추가해주지 않는다.
그래서 앞서 Point3D객체를 생성하는데, Point클래스의 기본생성자가 없다는 에러가 발생한 것이다.
Point(){}가 없어서 발생한 에러다.
그래서 항상 클래스를 만들 때, 기본 생성자 작성은 필수이다.
위의 에러를 해결하기 위해서는 2가지 방법이 있다.
1. Point의 기본생성자 Point(){} 를 작성해주기
2. Point3D의 생성자의 첫번째 줄에 super()가 아닌, super(x, y);로 수정해서 Point의 기본생성자가 아닌, Point(int x, int y)를 호출하도록 하기
2번 방법의 경우, 조상의 멤버는 조상의 생성자가 초기화 하도록 하는게 맞다고 했으므로, 이렇게 하는 방법도 맞다.
하지만, 기본생성자를 추가해주는 것이 좋은 방법이다.
'JAVA' 카테고리의 다른 글
import문, static import문 (0) | 2022.03.31 |
---|---|
패키지, 클래스 패스 (0) | 2022.03.31 |
오버라이딩 (overriding) (0) | 2022.03.30 |
단일 상속, Object 클래스 (0) | 2022.03.30 |
클래스 간의 관계, 상속과 포함 (0) | 2022.03.30 |
댓글
이 글 공유하기
다른 글
-
import문, static import문
import문, static import문
2022.03.31 -
패키지, 클래스 패스
패키지, 클래스 패스
2022.03.31 -
오버라이딩 (overriding)
오버라이딩 (overriding)
2022.03.30 -
단일 상속, Object 클래스
단일 상속, Object 클래스
2022.03.30