7-1.상속(상속)
상속은 이미 잘 개발된 클래스를 재사용해서 새로운 클래스를 만들기 때문에 중복되는 코드를 줄여 준다.
예를 들어, field1, field2, method1(), method2()를 가지는 클래스를 작성한다고 가정해보자. field1과 method1()을 가지고 있는 클래스가 있다면, 4개를 모두 처음부터 작성하는 것보다는 클래스를 상속하고, field2와 method2()만 추가 작성하는 것이 보다 효율적이고 개발 시간을 절약해준다.
클래스 상속
프로그램에서는 자식이 부모를 선택한다. 자식 클래스를 선언할 때 어떤 부모 클래스를 상속받을 것인지 결정하고, 선택된 부모 클래스는 다음과 같이 extends 뒤에 기술한다.
class 자식클래스 extends 부모클래스 {
//필드
//생성자
//메소드
}
*자바에서 상속의 특성
1. 여러 개의 부모 클래스를 상속할 수 없다. 그러므로 extends 뒤에는 단 하나의 부모 클래스만 와야 한다.
2. 부모 클래스에서 private 접근 제한을 갖는 필드와 메소드는 상속 대상에서 제외된다. 그리고 부모 클래스와 자식 클래스가 다른 패키지에 존재한다면 default 접근 제한을 갖는 필드와 메소드도 상속 대상에서 제외된다.
부모 생성자 호출
현실에서 부모 없는 자식이 있을 수 없듯이 자바에서도 자식 객체를 생성하면, 부모 객체가 먼저 생성되고 그다음에 자식 객체가 생성된다.
부모 생성자는 자식 생성자에 숨어 있다. 부모 생성자는 자식 생성자의 맨 첫 줄에서 호출된다.
ex)
부모 클래스
public class People {
public String name;
public String ssn;
public People(String name, String ssn) {
this.name = name;
this.ssn = ssn;
}
}
자식 클래스
public class Student extends People {
public int studentNo;
public Student(String name, String ssn, int studentNo) {
super(name, ssn); --> 부모 생성자 호출
this.studentNo = studentNo;
}
}
자식 객체 이용
pubic class StudentExample {
public static void main(String[] args) {
Student student = new Student("홍길동", "12345", 1);
System.out.println("name: " + student.name);
System.out.println("ssn: " + student.ssn);
System.out.println("studentNo: " + student.studentNo);
}
}
*부모 생성자를 호출하지 않으면 "Implicit super constructor 부모클래스 is undefined. Must explicitly invoke another constructor"라는 컴파일 에러가 발생
메소드 재정의 (overiding)
부모 클래스의 모든 메소드가 자식 클래스에 맞게 설계되어 있다면 가장 이상적인 상속이지만, 어떤 메소드는 자식 클래스가 사용하기에 적합하지 않을 수도 있다. 이 경우 상속된 일부 메소드는 자식 클래스에서 다시 수정해서 사용해야 한다. 자바는 이런 경우를 메소드 재정의 즉, 오버라이딩이라고 한다.
*메소드 재정의 방법
- 부모의 메소드와 동일한 시그너처(리턴 타입, 메소드 이름, 매개 변수 목록)를 가져야 한다.
- 접근 제한을 더 강하게 재정의할 수 없다.
- 새로운 예외(Exception)를 throws할 수 없다.
부모 메소드 호출
자식 클래스에서 부모 클래스의 메소드를 재정의하게 되면, 부모 클래스의 메소드는 숨겨지고 재정의된 자식 메소드만 사용된다. 그러나 자식 클래스 내부에서 재정의된 부모 클래스의 메소드를 호출해야 하는 상황이 발생한다면 명시적으로 super 키워드를 붙여서 부모 메소드를 호출할 수 있다.
ex)
super.부모메소드();
final 클래스와 final 메소드
final 키워드는 클래스, 필드, 메소드를 선언할 때 사용할 수 있는데, 해당 선언이 최종 상태이고 결코 수정될 수 없음을 뜻한다.
클래스와 메소드를 선언할 때 final 키워드가 지정되면 상속과 관련이 있다는 의미
상속할 수 없는 final 클래스
클래스를 선언 할 때 final 키워드를 class 앞에 붙이면 이 클래스는 최종적인 클래스이므로 상속할 수 없는 클래스가 된다.
ex)
public final class 클래스 {...} -> 상속 불가
재정의할 수 없는 final 메소드
메소드를 선언할 때 final 키워드를 붙이면 이 메소드는 최종적인 메소드이므로 재정의할 수 없는 메소드가 된다.
ex)
public final 리턴타입 메소드(매개변수) {...} -> 오버라이딩 불가
protected 접근 제한자
protected는 public과 default 접근 제한의 중간쯤에 해당한다. 같은 패키지에서는 default와 같이 접근 제한이 없지만 다른 패키지에서는 자식 클래스만 접근을 허용한다.
다른 패키지 있을 때
ex)
import sec01.exam07.pack1.A;
public class D extends A {
public D(){
super(); --> 이렇게 해서 접근 가능
this.field = "value";
this.method();
}
}