-
클래스의 super와 super()백엔드/자바 2020. 7. 28. 02:25
super란?
부모 클래스로부터 상속받은 필드(멤버변수)나 메소드를 자식클래스에서 참조하는데 사용하는 참조 변수.
this를 써서 인스턴스 변수와 지역 변수를 구분하던 것처럼 super를 이용하며
부모 클래스의 변수와 자식 클래스의 변수를 구분하여 사용할 수 있다.
예시를 보면 더 쉽게 이해할 수 있다.
인스턴스 변수가 선언된 부모 클래스
class Parents{ int test_num = 10; }
부모 클래스의 인스턴스 변수와 이름이 같은 변수를 초기화한 자식 클래스
class Child extends Parents{ int test_num = 15; public void test_method() { System.out.println("부모 클래스가 가진 값: "+super.test_num); System.out.println("자식 클래스가 가진 값: "+test_num); System.out.println("자식 클래스가 가진 값: "+this.test_num); } }
자식 클래스 객체를 만들어서 메서드를 실행한 코드
public class Test { public static void main(String[] args) { Child child = new Child(); child.test_method(); } }
코드를 실행한 결과는 위와 같다.
위 결과를 보면 알 수 있듯이 super를 통해서 변수가 부모것인지 자식것인지 구분해줄 수 있다.
단, super도 this와 마찬가지로 인스턴스 메서드 안 에서만 사용이 가능하다.
클래스 메서드에선 사용이 불가능하다.
(2) super( )란?
super()는 자식 클래스에서 부모 클래스의 생성자를 호출하는 메서드다.
자식 클래스의 생성자에서 조상 클래스 생성자를 호출하는 경우 사용한다.
초기화 블록과 생성자는 상속되지 않으므로 별도로 super()를 불러서 사용해야 한다.
예를 들어보자.
부모 클래스
class Parents{ int x; int y; Parents(int x, int y){ this.x = x; this.y = y; } public String getVar() { return "x: "+x+" y: "+y; } }
자식 클래스
class Child extends Parents{ int z; Child(int x, int y, int z){ this.x = x; this.y = y; this.z = z; } public String getVar() { return "x: "+x+" y: "+y+" z: "+z; } }
예를 들어 위와 같은 부모, 자식 클래스가 있다고 가정해보자.
위 클래스를 실행한 결과는 어떨까?
이미 위의 스크린샷을 보면 알겠지만 빨간 줄로 인해 해당 클래스들의 실행은 에러가 난다.
과연 왜 그럴까?
어떤 클래스든 사용하기 위해서는 객체가 필요하다.
그런데 객체를 만들 때 필수적으로 동반되는 작업이 생성자 실행이다.
생성자가 실행되지 않고선 객체를 만들 수 없기 때문이다.
그런데 이때 중요한 사실 하나를 알고가야 한다.
만약 코드 내에 어떠한 생성자가 없다면 자바 컴파일러는 자동으로 기본 생성자를 만들어준다.
단, 어떠한 형식의 생성자라도 있다면 컴파일러는 기본 생성자를 만들지 않는다.
위 원칙을 생각하고 다시 코드로 돌아가보자.
위의 빨간 박스안을 보면 알겠지만 부모 클래스에 이미 2개 정수를 매개변수로 받는 생성자가 생성되있다.
그래서 자바 컴파일러는 별도의 기본 생성자를 생성하지 않는다.
자식클래스로 돌아와 자식클래스의 생성자를 살펴보자.
x,y,z값을 매개변수로 받는데 이 중에서 x와 y의 값은 부모 클래스로부터 빌려온 멤버다.
그런데 부모의 객체를 생성하기 위해서는 기본 생성자가 아닌 x,y값을 넣어준 생성자가 필요하다.
그런데 위의 코드를 보면 알겠지만, x,y값을 넣어준 생성자가 없다.
그렇기 때문에 오류가 나는 것이다.
이것을 해결할 수 있는 방법은 두 가지다.
첫번째는 부모 클래스에 기본 생성자를 생성해주는 것이다.
부모 클래스에 기본 생성자를 만들고 돌아와보니 컴파일 오류가 없어졌다.
왜 그런걸까?
자바의 모든 클래스는 거슬러 올라가면 최종적으로 Object라는 클래스를 상속한다.
상속 관계에 없는 어떠한 클래스라도 이 Object를 상속받는다.
이는 곧 모든 클래스가 Object의 생성자를 가지고 있다는 말이 된다.
그리고 모든 클래스가 실행될 때 이 Object의 생성자도 실행된다는 말이다.
그런데 코드에는 없다. 어디간걸까?
바로 컴파일러가 컴파일 시 자동으로 코드에 추가해준다.
즉 우리가 직접 치진 않았어도 자동으로 추가해준다.
위에서 언급했던 원칙을 기억해보면 이것과 연관있는 것을 알 수 있다.
일반적으로 우리가 상속을 쓰지 않으면 super() 따위는 신경쓰지도 않는다.
하지만 자바의 구조상 Object를 무조건 상속 받아야 하고 실행해야 한다.
그래서 컴파일러가 Object클래스를 상속받게 하기 위해 생성자가 실행될 때
그 안에 자동으로 매번 super()를 추가해준다. 그렇기 때문에 위와 같은 원칙이 생긴 것이다.
즉 누가 써주지 않아도 자동으로 기본 생성자를 만들어준다는 것이다.
다만, 어떤 형식을 갖춘 생성자가 있으면 기본 생성자를 만들어주지 않기 때문에
위의 예시에선 자식 클래스가 부모 클래스를 상속받을 때 부모 클래스가 요구하는 생성자 조건을
맞추지 못했고 그 결과 부모 객체를 생성하지 못해 컴파일 에러가 난 것이다.
위와 같이 부모 클래스에 기본 생성자를 만들어줬다면
자식 클래스의 생성자 코드는 컴파일시 우리가 안써줘도 위와 같은 형식으로 super()가 붙는다.
이전에는 기본 생성자가 없어서 super()를 붙여도 객체를 불러올 수 없어 에러가 난 것이다.
다음으로 두번째 해결책은 부모 클래스의 생성자 조건에 맞게 super()를 생성해주는 것이다.
부모 클래스의 생성자는 x와 y값을 요구했으므로 부모 생성자를 super로 불러오고 x,y를 넣은 것이다.
이렇게 할 경우 부모 클래스의 기본 생성자가 없더라도 요구조건을 맞췄으므로 오류가 안난다.
이제 실제로 위 코드를 실행해보면 오류가 나지 않은 결과물을 얻을 수 있다.
여기서 우리가 기억해야할 건 이거다.
- 컴파일러는 자동으로 클래스 내에 기본 생성자를 생성해준다.
- 단, 다른 생성자가 있으면 기본 생성자를 생성하지 않는다.
- 가급적이면 클래스를 만들 때 기본 생성자는 만들어어야 한다.
'백엔드 > 자바' 카테고리의 다른 글
생성자(Constructor) (0) 2020.08.05 클래스 / 메소드 오버라이딩(method overriding) (0) 2020.07.28 클래스의 상속(inheritance) (0) 2020.07.28 초기화 (0) 2020.07.27 메서드(method)에 대해서 (0) 2020.07.27