✅ 형태
class 자식클래스 extends 부모클래스 {
// 필드
// 생성자
// 메소드
}
- 다중 상속은 되지 않으므로, extends 뒤에는 단 하나의 부모 클래스만 와야 한다 !
- 부모 객체 생성 후 자식 객체 생성하기
※ 모든 객체는 클래스의 생성자를 호출해야 한다. 부모 객체도 예외는 아니다. 부모 생성자는 자식 생성자의 맨 첫 줄에서 호출된다.
🔸 만약, 자식 생성자가 명시적으로 선언되지 않았다면 컴파일러는 다음과 같은 기본 생성자를 생성한다.
public 자식클래스(){
super();
}
🤔 super( ) ? 부모의 기본 생성자를 호출한다.
🔸 만약, 직접 자식 생성자를 선언하고 명시적으로 부모 생성자를 호출하고 싶다면 다음과 같이 작성한다.
public 자식클래스(매개변수 선언, ... ){
super(매개값, ...);
}
🤔 super(매개값, ...) ? 매개값의 타입과 일치하는 부모 생성자를 호출한다.
└ 일치하는 부모 생성자가 없을 경우 → 컴파일 오류 발생
@Override
🤔 메소드 오버라이딩(Overriding) ? 상속된 메소드의 내용이 자식 클래스에 맞지 않을 경우, 자식 클래스에서 동일한 메소드를 재정의하는 것
※ 메소드가 오버라이딩 되었다면, 부모 객체의 메소드는 숨겨지지 때문에 자식 객체에서 메소드를 호출하면 오버라딩된 자식 메소드가 호출된다.
오버라이딩 규칙
1. 부모의 메소드와 동일한 시그너처(리턴 타입, 메소드 이름, 매개변수 리스트)를 가져야 한다.
2. 접근 제한을 더 강하게 오버라이딩 할 수 없다.
┖ 부모 메소드가 public 접근 제한을 가지고 있을 경우, 오버라이딩하는 자식 메소드는 defaul나 private 접근 제한으로 수정할 수 없다는 뜻이다.
3. 새로운 예외(Exception)를 throws할 수 없다.
부모 메소드 호출 (super)
※ 자식 클래스 내부에서 오버라이딩된 부모 클래스의 메소드를 호출해야 하는 상황이 발생한다면, 명시적으로 super 키워드를 붙여서 부모 메소드를 호출할 수 있다.
⭐ super는 부모 객체를 참조하고 있기 때문에 부모 메소드에 직접 접근할 수 있다 !
super.부모 메소드( );
🤔 final ? 해당 선언이 최종상태이고, 절대 수정할 수 없음을 뜻한다.
└ 클래스, 필드, 메소드 시에 사용할 수 있다.
✅ 형태
public final class 클래스 { ... }
✅ 특징
- 클래스를 선언할 때 final 키워드를 class 앞에 붙이게 되면 이 클래스는 최종적인 클래스 이므로, 상속할 수 없다는 클래스 가 된다.
- final 클래스는 부모 클래스가 될 수 없으므로 자식 클래스를 만들 수 없다.
✅ 형태
public final 리턴타입 메소드 ([매개변수, ...]) { ... }
✅ 특징
- 메소드를 선언할 때 final 키워드를 붙이게 되면, 이 메소드는 최종적인 메소드이므로, 오버라이딩할 수 없는 메소드 가 된다.
- 부모 클래스를 상속해서 자식 클래스를 선언할 때 부모 클래스에 선언된 final 메소드는 자식 클래스에서 재정의할 수 없다.
접근 제한 | 적용할 내용 | 접근할 수 없는 클래스 |
---|---|---|
public | 클래스, 팔드, 생성자, 메소드 | 없음 |
protected | 팔드, 생성자, 메소드 | 자식 클래스가 아닌 다른 패키지에 소속된 클래스 |
default | 클래스, 팔드, 생성자, 메소드 | 다른 패키지에 소속된 클래스 |
private | 팔드, 생성자, 메소드 | 모든 외부 클래스 |
🤔 타입변환 ? 데이터 타입을 다른 데이터 타입으로 변환하는 행위
🤔 다형성 ? 같은 타입이지만 실행 결과가 다양한 객체를 이용할 수 있는 성질
🤔 자동 타입 변환(Promotion) ? 프로그램 실행 중 자동적으로 타입 변환이 일어나는 것
✅ 형태
✅ 특징
- 자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있다.
- 부모타입으로 자동 타입 변환된 이후에는 부모 클래스에 선언된 필드와 메소드만 접근이 가능하다.
ex) Cat 객체가 Animal 객체에 상속되어 있을 때, 타입변환
Cat cat = new Cat(); ┐
│ Animal animal = new Cat(); 도 가능하다 !
Animal animal = cat; ┘
※ 예외 ! 메소드가 자식 클래스에서 오버라이딩되었다면, 자식 클래스의 메소드가 대신 호출된다.
❓ 자동 타입 변환이 필요한 이유
: 다형성을 구현하는 기술적 방법 때문이다. 주로 필드의 값을 다양화함으로써 실행 결과가 다르게 나오도록 구현하는데, 필드의 타입은 변함이 없지만, 실행 도중에 어떤 객체를 필드로 저장하느냐에 따라 실행 결과가 달라질 수 있다.
동일한 타입의 값들은 배열로 관리하는 것이 유리하다.
🤔 강제 타입 변환 ? 부모 타입을 자식 타입으로 변환하는 것
✅ 형태
- 자식 타입이 부모 타입으로 자동 변환하면, 부모 타입에 선언된 필드와 메소드만 사용 가능하다는 제약 사항이 따른다.
- 만약 자식 타입에 선언된 필드와 메소드를 꼭 사용해야 한다면 강제 타입 변환을 해서 다시 자식 타입으로 변환한 다음 자식 타입의 필드와 메소드를 사용하면 된다.
※ 강제 타입 변환은 자식 타입이 부모 타입으로 변환되어 있는 상태에서만 가능하다.
☞ 따라서 부모 타입의 변수가 부모 객체를 참조할 경우 자식 타입으로 변환할 수 없다.
Parent parent = new Parent();
Child child = (Child) parent; // 강제 타입 변환을 할 수 없다.
✅ 형태
boolean result = 좌향(객체) instanceof 우향(타입)
🤔 실체 클래스 ? 객체를 직접 생성할 수 있는 클래스
🤔 추상 클래스 ? 실체 클래스들의 공통적인 특성을 추출해서 선언한 클래스
✅ 특징
- 추상 클래스와 실체 클래스는 상속의 관계를 가지고 있다.
- 개념에서 말하는 특성 이란 ? 필드와 메소드 를 말한다.
- 추상 클래스는 객체를 직접 생성해서 사용할 수 없다. 즉, new 연산자를 사용해서 인스턴스를 생성시키지 못한다.
- 추상 클래스는 새로운 실체 클래스를 만들기 위해 부모 클래스로만 사용된다.
⭐ class 실체 extends 추상 { ... }
✅ 용도
첫번째, 실체 클래스들의 공통된 필드와 메소드의 이름을 동일할 목적
: 동일한 데이터와 기능임에도 불구하고 이름이 다를 경우, 객체마다 사용방법이 달라진다. 따라서 추상 클래스에 동일한 데이터와 메소드를 선언하고, 실체 클래스는 추상 클래스를 상속함으로써 필드와 메소드 이름을 통일시킨다.
두번째 실체 클래스를 작성할 때 시간을 절약
: 공통적인 필드와 메소드는 추상 클래스에 모두 선언하고, 실체 클래스마다 다른 점만 실체 클래스에 선언하게 되면 실체 클래스를 작성하는 데 시간을 절약할 수 있다.
✅ 선언
public abstract class 클래스() {
// 필드
// 생성자
// 메소드
}