상속과 오버라이딩
2025. 2. 23. 19:09ㆍJava/객체지향
1. 상속
1-1. 상속이란?
- 부모 클래스가 가지는 멤버(필드, 메소드)를 자식 클래스가 물려 받아 자신의 멤버인 것처럼 사용할 수 있도록 만든 기술
- 멤버 외에도 부모 클래스의 타입 또한 상속이 된다. (다형성의 토대)
- 단, 생성자와 초기화블럭은 상속되지 않는다.
- 자손클래스의 인스턴스 = 조상 클래스의 멤버 + 자손 클래스의 멤버
- 따라서 자손 클래스의 멤버개수는 조상 클래스보다 항상 같거나 많다
- 자바는 단일상속(자식 클래스는 하나의 부모 클래스만 가지는)만 지원한다.
1-2. 상속의 장점
- 클래스 간 계층 관계를 형성하여 다형성 문법의 토대가 된다.
- 코드의 재사용성을 높히고 코드의 중복을 제거하여 프로그램의 생산성과 유지보수에 기여한다.
- 코드의 추가 및 변경이 용이: 상속을 통해 클래스를 작성하면 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있고 코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 용이하다.
1-3. 상속 구현법 : extends 키워드
public class Cat extends Animal { }
// Animal -> 상속 해주는 클래스: 조상클래스, 부모클래스, 상위 클래스, 기반(base)클래스
// Cat -> 상속 받는 클래스: 자손클래스, 자식클래스, 하위클래스, 파생(derived)클래스
2. 클래스 간의 관계
상속 관계 (Is-a) | 포함 관계 (Has-a) | |
의미 | 클래스 간 상속 관계를 맺는 것 "자식 클래스는 부모 클래스(의 한 종류)이다.” |
한 클래스의 멤버변수로 다른 클래스 타입의 참조변수를 선언하는 것 "부모 클래스는 자식 클래스를 갖고 있다." |
관계 | 부모-자식 | 클래스-멤버변수 |
예시 | 차-소방차 소방차는 차(의 한 종류)이다. |
차-바퀴 차는 바퀴를 갖고 있다. |
3. super, super()
3-1. super
- 자식 클래스의 인스턴스 생성 시 부모 생성자를 호출하여 부모 클래스의 인스턴스도 함께 생성하게 되는데, 이 때 생성한 부모 인스턴스의 주소를 보관하는 레퍼런스 변수
- 자손클래스에서 조상클래스로부터 상속받은 멤버를 참조하는데 사용된다.
- 자식 클래스 내의 모든 생성자와 메소드 내에서 묵시적으로 사용할 수 있다.
- 멤버변수와 지역변수의 이름이 같을 때 this를 써서 구별했듯이, 상속받은 멤버와 자신의 멤버가 이름이 같을 때는 상속받은 멤버에 super을 붙여 구분할 수 있다
- this와 마찬가지로 super 역시 static메서드에서는 사용할 수 없고 인스턴스 메서드에서만 사용할 수 있다
3-2. super()
- 자식 클래스의 생성자에서 부모 생성자를 호출하는 구문
- 인자와 매개변수의 타입, 갯수, 순서가 일치하는 부모의 생성자를 호출한다.
- 부모 클래스의 private 생성자는 호출 불가
- this()는 같은 클래스의 다른 생성자를 호출하는 데 사용되지만, super()는 조상클래스의 생성자를 호출하는 데 사용된다.
- 자손 클래스 인스턴스 생성: 조상 클래스 생성자 호출 -> 후손 클래스 생성자 호출
조상클래스의 멤버의 초기화 작업이 수행되어야 하기 때문에 "자손 클래스의 생성자에서" 조상클래스의 생성자가 호출되어야한다. - Object 클래스를 제외한 모든 클래스의 생성자 첫 줄에 super()를 컴파일러가 자동적으로 삽입한다.
public Car(){
// 모든 생성자에는 맨 첫 줄 위에 super() 를 컴파일러가 자동으로 추가한다.
// 부모의 기본 생성자를 호출하는 구문으로 명시적, 묵시적으로 사용 가능
super(); //Object()
// 모든 클래스는 Object라는 클래스를 최상위 부모로 삼고있었음. (자동)
// 기본적으로 쓰던 함수들 equals(), clone() 등등 모두 Object의 메서드임
System.out.println("Car 클래스 기본 생성자 호출");
}
3-3. Object클래스 - 모든 클래스의 조상
- Object클래스는 모든 클래스의 상속계층도 최상위에 있는 조상클래스이다.
- 다른 클래스로부터 상속 받지 않는 모든 클래스들은 자동적으로 Object클래스로부터 상속받게 한다
- 자바의 모든 클래스들은 Object클래스의 멤버들을 상속 받기 때문에 Object클래스에 정의된 멤버들을 사용할 수 있다. (toString(), equals()등..)
4. 오버라이딩
4-1. 오버라이딩이란?
- 오버라이딩이란 조상클래스로부터 상속받은 메서드의 내용을 변경하는 것이다.
- 상속받은 메서드를 그대로 사용하기도 하지만, 자손 클래스 자신에 맞게 변경해야하는 경우 조상의 메서드를 오버라이딩하여 사용한다
- Spring에서 제공하는 @Override 어노테이션은 오버라이딩 규칙에서 어긋나는 경우 에러를 뱉는다.
4-2. 오버라이딩의 조건
- 메소드명, 리턴타입 동일
- 매개변수의 타입, 개수, 순서가 동일
- 부모 클래스의 private, final 메소드는 오버라이딩 불가능 (protected 가능)
- 접근제어자는 부모 메소드와 같거나 더 넓은 범위여야 함
- 예외처리는 같은 예외이거나 더 구체적(하위)인 예외를 처리해야 함
- 인스턴스메서드를 static메서드로 또는 그 반대로 변경할 수 없다.
public class SuperClass {
//오버라이딩 테스트 기준 메소드
public void method(int num) {}
private void privateMethod() {}
public final void finalMethod() {}
protected void protectedMethod() {}
}
public class SubClass extends SuperClass {
//오버라이딩 규칙
//규칙에서 어긋나는 경우 @Override 어노테이션이 에러 뱉음
//1. 메소드명, 리턴 타입, 매개변수 개수&타입&순서 일치해야 성립
@Override
public void method(int num) {}
//public void method(String num) {} //매개변수 타입 불일치
//public void method(int num) { return 0; } //리턴 타입 불일치
//public void method2(int num) {} //메소드명 불일치
//2. private, final 메소드 오버라이딩 불가, protected 가능
@Override
//private void privateMethod() {} //불가능
//public void finalMethod() {} //불가능
//protected void protectedMethod() {} //가능
//3. 접근 제어자 범위를 좁히는 것은 불가능
// public > protect > default > private
// protect -> default로 변경 불가
// void protectedMethod() {} //불가
// protect -> public은 변경 가능
public void protectedMethod() {} //가능
}
4-3. 오버로딩 vs. 오버라이딩
- 오버로딩: 기존에 없는 새로운 메서드를 정의하는 것. 즉 이름은 똑같지만 "매개변수를" 다르게 하는 것.
- 오버라이딩: 상속받은 메서드의 "내용을" 변경하는것.