상속은 기존의 클래스를 재사용해 새로운 클래스를 작성하는 것인데, 적은 양의 코드로 새로운 클래스의 코드를 작성할 수 있고 코드를 공통적으로 관리해 코드의 추가 및 변경이 매우 용이하다.
상속의 장점
1. 코드의 재사용성 증가
2. 중복된 코드의 제거로 인한 생산성의 향상 및 유지보수가 편해짐.
1) 상속의 예시
class Child extends Parent{
// 내용
}
상속받고자 하는 클래스의 이름 뒤에 extends와 상속 받을 클래스 이름을 적는다.
상속은 부모에서 선언과 정의를 모두 하며 자식은 메서드와 변수를 그대로 사용이 가능해 오버라이딩을 따로 할 필요가 없다. (단일상속 = 하나의 클래스에 하나만 상속이 가능하다)
상속을 해주는 클래스를 '조상 클래스'
상속을 받는 클래스를 '자손 클래스'
자손 클래스는 조상 클래스의 모든 멤버를 상속
받기에, 포함관계로 따지면 자손 클래스 속에 조상 클래스가 존재한다.
생성자와 초기화 블럭은 상속되지 않는다. 멤버만 상속된다는점을 기억해야한다.
오버라이딩(Overriding)
이렇게 조상 클래스로부터 상속받은 메서드의 내용을 변경할 수 있는데, 변경하는 것을 오버라이딩(overriding)이라 한다. 오버라이딩을 사용하기 위해선 몇 개의 조건이 필요하다.
1. 자손 클래스에서 오버라이딩 하는 메서드는 조상 클래스의 메서드와 이름이 같아야 한다.
2. '' 매개변수가 같아야 한다.
3. '' 반환타입이 같아야 한다.
이 3개의 조건을 정리하면 선언부가 서로 일치해야 한다는 것이다.
(다만 접근 제어자와 예외는 제한된 조건에서 다르게 변경이 가능하다.)
접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경 할 수 없다.
= 만약 조상 클래스에서 정의된 메서드의 접근 제어자가 protected라면, 이를 오버라이딩하는 자손 클래스의 메서드는 접근 제어자가 protected나 public이어야 한다. (대부분은 같은 범위의 접근 제어자 사용)
(public, protected,default, private 순으로 넓은 것에서 좁은 순으로 나열한 것이다.)
조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없다.
오버라이딩과 오버로딩을 혼동할 수 있는데, 이 한마디로 정리가 가능하다.
오버로딩은 기존에 업슨 새로운 메서드를 정의하는 것 = new
오버라이딩은 상속받은 메서드의 내용을 변경하는 것 = change, modify
super라는 변수가 있다
super은 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조할 때 사용되는 참조 변수이다.
(상위 클래스를 호출할 때 사용)
변수부분에서 멤버 변수와 지역 변수의 이름이 같을 때 this를 붙여 구분한 것 처럼, 상속받은 멤버와 자신의 클래스에 정의된 멤버 이름이 같을 때는 super을 붙여 구별 할 수 있다. (조상 클래스와 자손 클래스의 멤버를 구분하기 위해 사용)
모든 인스턴스 메서드에는 자신이 속한 인스턴스의 주소가 지역변수로 저장되는데, 이것이 참조변수인 this와 super 값이 된다.
클래스 메서드(static)은 인스턴스와 관련이 없어 this와 마찬가지로 클래스 메서드에서 사용이 불가능하고 (super은) 인스턴스 메서드에서만 사용이 가능하다
1) super 클래스 예시
class Parent{
int x = 10;
}
class Child extends Parent{
void method(){
System.out.println(" x = "+x);
System.out.println(" this.x = "+this.x);
System.out.println(" super.x = "+super.x);
}
}
class Main {
public static void main(String[] args){
Child c = new Child();
c.method();
}
}
다음 위와 같은 코드가 있을때 출력을해보면 다음과 같다.
이는 x, this.x, super.x가 모두 같은 변수를 의미하고 있어 모두 같은 값이 출력됨을 확인가능하다.
그럼 만약에 자손 클래스에도 동일한 변수가 있는데 값이 다르다면??
class Main{
public static void main(String[] args){
Child c = new Child();
c.method();
}
}
class Parent{
int x = 10;
}
class Child extends Parent{
int x = 20;
void method(){
System.out.println(" x = "+x);
System.out.println(" this.x = "+this.x);
System.out.println(" super.x = "+super.x);
}
}
이 전의 예제와 다른 출력 결과를 확인할 수 있다.
이전 예제와 달리 같은 이름의 멤버변수가 조상 클래스와 자손 클래스에 각각 있는데, super.x와 this.x는 서로 다른 값을 참조하게 된다. 여기서 super.x는 조상 클래스로부터 상속받은 멤버변수 x를 말하고, this.x는 자손 클래스에서 상속받은 멤버변수를 말한다.
this와 super을 비교해보았는데, this()와 마찬가지로 super()가 존재한다. this()가 생성자였던 것 처럼. super()도 생성자다. this()는 같은 클래스의 다른 생성자를 호출할 때 사용되지만, super()은 조상 클래스이 생성자를 호출하는데 사용된다.
'Language > Java' 카테고리의 다른 글
추상 클래스(abstract class)와 인터페이스(interface) (0) | 2022.01.23 |
---|---|
내부 클래스(inner class) (0) | 2022.01.22 |
생성자(Constructor) (0) | 2022.01.21 |
오버로딩(overloading) (0) | 2022.01.20 |
클래스 메서드(static)와 인스턴스 메서드 (static은 무엇일까) (0) | 2022.01.20 |