프로그램에서는 자식이 부모를 선택
=> 자식 클래스 선언 시 어떤 부모 클래스를 상속받을 것인지 결정
다중 상속 허용하지 않고 단일 상속 가능
부모 클래스에서 private 접근 제한을 갖는 필드와 메서드는 상속 대상에서 제외
클래스 상속 예시
class SportCar extends Car{
}
1. 기본 생성자 호출
기본 생성자 호출 예시
class Parent {
Parent() {
System.out.println("부모 클래스의 기본 생성자 호출");
}
}
class Child extends Parent {
Child() {
// 부모 클래스의 기본 생성자가 자동 호출됨
System.out.println("자식 클래스의 생성자 호출");
}
}
public class Test {
public static void main(String[] args) {
Child child = new Child(); // 자식 클래스의 생성자 호출
}
}
=> 출력 내용
부모 클래스의 기본 생성자 호출
자식 클래스의 생성자 호출
2. 명시적 생성자 호출
super() 키워드를 사용하여 부모 클래스의 생성자를 호출
=> 부모 클래스의 생성자가 제공하는 인자와 일치하는 값을 전달
super()의 위치는 자식 클래스 생성자의 첫 줄에 위치
명시적 생성자 호출 예시
class Parent {
Parent(String message) {
System.out.println("부모 클래스의 생성자 호출: " + message);
}
}
class Child extends Parent {
Child() {
// 부모 클래스의 생성자 호출 (매개변수가 있는 생성자)
super("부모 클래스의 메시지");
System.out.println("자식 클래스의 생성자 호출");
}
}
public class Test {
public static void main(String[] args) {
Child child = new Child(); // 자식 클래스의 생성자 호출
}
}
=> 출력 내용
부모 클래스의 생성자 호출: 부모 클래스의 메시지
자식 클래스의 생성자 호출
부모 클래스로 부터 상속된 일부 메서드는 자식 클래스에서 재정의
메서드 재정의 시 부모 객체의 메서드는 숨겨지고, 재정의된 자식 메서드가 호출
1. 메서드 재정의 방법
부모 메서드와 동일한 시그니처(리턴 타입, 메서드 이름, 매개 변수 목록)
접근 제한을 더 강하게 재정의 할 수 없다.
새로운 예외를 throws 할 수 없다.
2. 부모 메서드 호출
class Parent {
void method1() {}
void method2() {}
}
class Child extends Parent{
void method2() {} // 재정의
void method3() {
method2(); // 재정의된 호출
super.method2(); // 부모 메서드 호출
}
}
1. 상속할 수 없는 final 클래스
final 클래스 예시
public final class String{} // 상속할 수 없는 클래스
2. 재정의할 수 없는 final 메서드
final 메서드 예시
public final void String{} // 재정의 불가한 메서드
자동 타입 변환 예시
class Animal{}
class Cat extends Anilmal {}
Cat cat = new Cat();
Animal animal = cat; // cat은 Animal로 자동 타입 변환 이루어짐
매개 변수의 타입이 클래스일 경우, 해당 클래스의 객체뿐만 아니라 자식 객체까지도 매개값으로 사용 가능
=> 매개값으로 어떤 자식 객체가 제공되느냐에 따라 메서드의 실행결과가 다양해 진다.
매개값의 자동 타입변환과 메서드 재정의를 이용하여 매개 변수의 다형성을 구현
class Parent{
String field1;
void method1() {}
void method2() {}
}
class Child extends Parent{
Strinf field2;
void method3() {}
}
class ChildExample{
public static void main(String[] args) {
Parent parent = new Child();
parent.field1 = "xxx";
parent.method1();
parent.method2();
//parent.field2 = "yyy"; // 불가능
//parent.method3(); // 불가능
// 강제 타입 변환 후 가능
Child child = (Child) parent;
child.field2 = "yyy"; // 가능
child.method3(); // 가능
}
}
public void method(Parent parent) {
if(parent instanceod Child) {
Child child = (Child) parent;
}
}
클래스들의 공통적인 특성을 추출해서 선언한 클래스
추상 클래스(부모 클래스)와 실체 클래스(자식 클래스)는 상속의 관계를 가지고 구현되어 실체 클래스는 추상 클래스의 모든 특성을 물려받고 추가적인 특성을 가짐
1. 공통된 필드와 메소드의 이름을 통일
=> 실체 클래스에 반드시 존재해야 할 필드와 메서드 선언
2. 실체 클래스를 작성할 때 시간 절약
=> 공통된 내용은 물려받고, 다른 점만 선언
abstract 키워드를 붙여야 한다.
new 연산자를 이용하여 객체 만들수 없다.
=> 상속을 통해서 자식 클래스 만들기 가능
추상 클래스 선언 예시
package sec03.exam01;
public abstract class Phone { // 추상 클래스
// 필드
public String owner;
// 생성자
public Phone(String owner) {
this.owner = owner;
}
// 메서드
public void turnOn() {
System.out.println("폰 전원을 켭니다.");
}
public void turnOff() {
System.out.println("폰 전원을 끕니다.");
}
}
메서드의 선언만 통일하고 실행 내용은 실체 클래스마다 다를 경우 사용
abstract 키워드와 함께 메서드의 선언부만 있고 메서드 실행 내용인 중괄호{}가 없는 메서드
실체 클래스는 반드시 추상 메서드를 재정의 하여야 함
추상 메서드 선언 , 재정의 예시
public abstract class Animal { // 추상 클래스
public String kind;
public void breathe() {
System.out.println("숨을 쉽니다.");
}
public abstract void sound(); // 추상 메서드
}
public class Cat extends Animal {
public Cat() {
this.kind = "포유류";
}
@Override
public void sound() { // 추상 메서드 재정의
System.out.println("냐옹");
}
}