super는 앞서 배운 this와 함께 객체를 참조할 수 있는 reference 변수이다.
this가 특정 객체 내에서 자기 자신의 객체를 참조할 수 있는 유일한 reference 변수라면,
super는 현재 객체의 바로 상위인 부모 클래스(super class)를 참조할 때 사용하는 reference 변수이다.
그렇다면 어떠한 경우에 super를 사용해 부모 클래스를 참조/지칭하게 되는지 예제와 함께 알아보자.
package kr.s24.object.supertest;
class Mother{
public String getLunch() {
return "밥";
}
}
class Daugther extends Mother{
//메서드 오버라이딩(재정의)
@Override
public String getLunch() {
return "빵";
}
public String getRice() {
//부모 클래스의 getLunch 메서드 호출
return super.getLunch();
}
}
public class SuperMain01 {
public static void main(String[] args) {
Daugther d = new Daugther();
System.out.println("딸은 " + d.getLunch() + "을 먹습니다.");
System.out.println("딸은 오늘은 왠지 " + d.getRice() + "이 먹고 싶습니다.");
}
}
package kr.s24.object.supertest;
class Parent{
public void play() {
System.out.println("피아노를 연주하다.");
}
}
class Child extends Parent{
//메서드 오버라이딩(재정의)
@Override
public void play() {
System.out.println("첼로를 연주하다.");
}
public void playSomething() {
super.play();
}
}
public class SuperMain02 {
public static void main(String[] args) {
Child ch = new Child();
ch.play();
ch.playSomething();
}
}
두 예제 모두 두 개의 클래스 간 상속 관계가 이루어진 것을 확인할 수 있다.
ex. class Daugther extends Mother, class Child extends Parent
또한, 모두 자식 클래스에서 부모 클래스의 메서드를 오버라이딩(재정의)하였다.
ex.
부모 : public String getLunch() {return "밥";}
자식 : public String getLunch() {return "빵";}
부모 : public void play() {System.out.println("피아노를 연주하다.");}
자식 : public void play() {System.out.println("첼로를 연주하다.");}
그리고 모두 자신만의 메서드를 생성하였는데, 이때 부모 클래스의 메서드를 호출하며 super를 사용한다.
ex.
public String getRice() {
return super.getLunch();
}
---
public void playSomething() {
super.play();
}
출력 결과)
딸은 빵을 먹습니다.
딸은 오늘은 왠지 밥이 먹고 싶습니다.
---
첼로를 연주하다.
피아노를 연주하다.
super를 통해 부모 클래스의 메서드를 호출한 결과, 재정의한 메서드가 아닌 부모의 원본 메서드가 출력된 것을 알 수 있다.
package kr.s24.object.supertest;
//부모 클래스
class People{
int a = 100;
//생성자 - 상속 관계를 맺으면 자동으로 생성
public People() {
super();
}
}
//자식 클래스
class Student extends People{
int b = 200;
//생성자 - 상속 관계를 맺으면 자동으로 생성
public Student() {
super();
}
}
public class SuperMain03 {
public static void main(String[] args) {
Student s = new Student();
System.out.println(s.a);
System.out.println(s.b);
}
}
super()는 그 형태에서 알 수 있듯 super 클래스의 생성자를 의미한다.
앞서 상속의 개념을 설명하며 모든 클래스는 Object를 상속받으며 기본적으로는 생략된다고 언급한 바 있다. 따라서 super() 생성자 역시 생략된 형태로 존재한다.
ex.
public People() {
super(); - Object의 생성자
}
public Student() {
super(); - 상속 받은 People 클래스의 생성자
}
그렇다면 직접 명시해야 하는 경우는 어떤 경우일까?
package kr.s24.object.supertest;
//부모 클래스
class People2{
int a;
//인자가 있는 생성자 정의
public People2(int a) {
this.a = a;
}
}
//자식 클래스
class Student2 extends People2{
//생성자
public Student2() {
super(100);
}
}
public class SuperMain04 {
public static void main(String[] args) {
Student2 st = new Student2();
System.out.println(st.a);
}
}
package kr.s24.object.supertest;
//부모 클래스
class Parent2{
int a;
int b;
//생성자
public Parent2(int a, int b) {
this.a = a;
this.b = b;
}
}
//자식 클래스
class Child2 extends Parent2{
//생성자
public Child2(int a, int b) {
//부모 클래스의 인자가 있는 생성자 호출
super(a, b);
}
}
public class SuperMain05 {
public static void main(String[] args) {
Child2 ch = new Child2(100, 200);
System.out.println(ch.a);
System.out.println(ch.b);
}
}
public Child2(int a, int b) {
super(a, b);
}
이를 응용하면 다음과 같다.
package kr.s24.object.supertest;
//부모 클래스
class Point{
int x;
int y;
//생성자
public Point(int x, int y) {
this.x = x;
this.y = y;
}
//메서드
public String getLocation() {
return "x:" + x + ", y:" + y;
}
}
//자식 클래스
class Point3D extends Point{
int z;
public Point3D(int x, int y, int z) {
super(x, y);
this.z = z;
}
//메서드 오버라이딩(재정의)
@Override
public String getLocation() {
return "x:" + x + ", y:" + y + ", z:" + z;
}
}
public class SuperMain06 {
public static void main(String[] args) {
//객체 선언 및 생성
Point3D p3 = new Point3D(100, 200, 300);
//getLocation 메서드 호출
System.out.println(p3.getLocation());
}
}
자식 클래스에서 멤버 변수 int z를 추가로 정의하였고
기본 생성자 외에 인자가 있는 생성자를 하나 더 정의한 다음,
'부모의' 인자가 있는 생성자를 super()로 호출,
상속 관계 형성으로 인해 부모 클래스의 멤버 변수를 사용할 수 있기 때문에 int x와 int y에 인자로 전달된 x,y를 대입해 주고
추가로 자신이 갖고 있는 멤버 변수 int z에 인자로 전달된 z를 대입해 준다.
ex.
public Point3D(int x, int y, int z) {
super(x, y);
this.z = z;
}
그리고 부모 클래스의 메서드 getLocation()을 재정의 하여 자신의 멤버 변수 z를 함께 반환한다.
ex.
부모 수행문 : return "x:" + x + ", y:" + y;
자식 수행문 : return "x:" + x + ", y:" + y + ", z:" + z;
자식 클래스의 객체를 생성할 때, 인자가 있는 생성자를 활용해 멤버 변수에 데이터들을 넣어주고
ex. Point3D p3 = new Point3D(100, 200, 300);
재정의한 getLocation() 메서드를 호출할 경우, 다음과 같은 출력 결과를 얻는다.
출력 결과)
x:100, y:200, z:300
이를 적용하여 마이너스 계좌 만들기를 진행하였다.
> 은행 프로그램 만들기(마이너스 계좌)