1. 상속
- 기존 클래스의 필드와 메서드를 새로운 클래스에서 재사용하게 해 줌
- “기존 클래스의 속성과 기능을 물려받는 것”
- extends 키워드 사용
- extends : -> (”내가 상대방을 안다”) 라고 생각 가능
public class ElectricCar extends Car
// public class ElectricCar -> Car 라고 생각 가능
📌 상속관계 용어
부모 클래스 (슈퍼 클래스)
- 상속을 통해 자신의 필드와 메서드를 물려주는 클래스
- 자식 클래스에 대해 전혀 모름
자식 클래스 (서브 클래스)
- 부모 클래스에게서 필드와 메서드를 상속받는 클래스
- 상속 예시 구조도
- 상속 예시 코드
public class Car {
public void move() {
System.out.println("차를 움직입니다.");
}
}
public class ElectricCar extends Car {
public void charge() {
System.out.println("차를 충전합니다.");
}
}
public class GasCar extends Car {
public void fillup() {
System.out.println("기름을 주유합니다.");
}
}
📌 다중 상속 불가! / 단일 상속만 가능!
1-1. 상속과 메모리 구조
// 상속받은 ElectricCar 클래스의 인스턴스 생성
ElectricCar electricCar = new ElectricCar();
- new ElectircCar()
- ElectricCar 클래스의 인스턴스 생성
- 또한 부모 클래스인 Car 인스턴스도 생성!!
- 참조값은 1개지만 내부에는 2개의 클래스 정보 (자기 자신, 부모 클래스) 정보가 존재함!
📌 상속 관계
단순히 부모 클래스의 멤버 변수, 메서드 를 물려받는 것이 아님
인스턴스 생성 시 부모 클래스도 함께 생성되는 것임!!
1-1-1. 상속과 메모리 구조 - 메서드 호출
// 상속받은 ElectricCar 객체의 메서드 호출
electricCar.charge();
// 부모 클래스의 메서드 호출
electricCar.move();
"상속 관계의 경우 ⇒ 인스턴스 내부에는 부모와 자식이 모두 존재, 어디서 메서드 찾을것인가?"
- 메서드 호출 과정
- 먼저 호출하는 변수의 타입(클래스)을 기준으로 선택
- 해당 기능이 없으면 부모 타입으로 올라가서 찾음 (반복)
- 최상위 부모에도 메서드가 존재하지 않으면 컴파일 에러!
- electricCar.charge();
- electricCar.move();
1-2. 메서드 오버라이딩
- 자세한 내용은 아래 링크
https://blogan99.tistory.com/62
1-3. 상속과 접근 제어
1-3-0. 접근 제어자
https://blogan99.tistory.com/114
1-3-1. 상속에서의 접근 제어자 사용 예시
public class Parent {
public int publicValue; // public 멤버 변수
protected int protectedValue; // protected 멤버 변수
int defaultValue; // default 멤버 변수
private int privateValue; // private 멤버 변수
// public 메서드
public void publicMethod() { System.out.println("Parent.publicMethod); }
// protected 메서드
protected void protectedMethod() { System.out.println("Parent.protectedMethod); }
// default 메서드
void defaultMethod() { System.out.println("Parent.defaultMethod); }
// private 메서드
private void privateMethod() { System.out.println("Parent.privateMethod); }
}
...
// 다른 패키지의 Child 클래스
public class Child extends Parent {
public void call() {
publicValue = 1; // public 멤버 변수 접근 가능
protectedValue = 1; // protected 멤버 변수 접근 가능
defaultValue = 1; // default 접근 불가! => 컴파일 에러
protectedValue = 1; // protected 접근 불가! => 컴파일 에러
publicMethod(); // public 메서드 접근 가능
protectedMethod(); // protected 메서드 접근 가능
defaultMethod(); // default 접근 불가! => 컴파일 에러
protectedMethod(); // protected 접근 불가! => 컴파일 에러
}
}
📌 protected 접근 제어자 ⇒ 상속 관계 or 같은 패키지 접근 허용!
1-4. super
- super 키워드 : 부모 참조
- 자식과 부모의 필드 명이 같거나 메서드가 오버라이드 되어 있으면
⇒ 부모의 필드나 메서드 접근 불가 ⇒ 부모 참조 위해서 super 사용!
public class Parent {
public String value = "parent";
public void printValue() {
System.out.println("Parent.value = " + value);
}
}
...
public class Child extends Parent {
public String value = "child";
@Override
public void printValue() {
System.out.println("Child.value = " + value);
}
public void call() {
System.out.println("this.value = " + this.value);
// 부모의 필드 (value) 접근
System.out.println("super.value = " + super.value);
this.printValue();
// 부모의 메서드 (printValue()) 접근
super.printValue();
}
}
public class Main {
public static void main(String[] args) {
Child child = new Child();
child.call();
}
}
/* 실행결과
this.value = child
super.value = parent
Child.value = child
Parent.value = parent
*/
1-5. super()
- 자식 클래스의 인스턴스 생성 시 자식 뿐만 아니라 부모도 생성됨 (https://blogan99.tistory.com/113)
- 따라서 각각의 생성자가 모두 호출되어야 함!!
📌 상속 관계 규칙
자식 클래스의 생성자에서 부모 클래스의 생성자를 반드시 호출해야 한다!!
- super(...) : 부모 생성자 호출
- 부모의 기본 생성자 호출 ( super() )은 생략 가능함
- 항상 생성자의 첫 줄에 작성해야 함!
- this(...) 와 함께 사용할 시 한 번은 super(...) 를 호출해야 함!
= 생성자 첫줄엔 this() 혹은 super() 를 작성해야 하는데 한번은 super()를 호출해야 함
- this(...) 와 함께 사용할 시 한 번은 super(...) 를 호출해야 함!
public class ClassA {
public ClassA() {
System.out.println("ClassA 기본생성자");
}
}
public class ClassB extends ClassA{
public ClassB(int a) {
// 부모의 기본 생성자 호출 생략 가능
// super();
System.out.println("ClassB 생성자 : a=" + a);
}
public ClassB(int a, int b) {
// 부모의 기본 생성자 호출 생략 가능
// super();
System.out.println("ClassB 생성자 : a=" + a + " b=" + b);
}
}
public class ClassC extends ClassB{
public ClassC() {
// 부모 클래스 (ClassB) 에 기본 생성자가 없기 때문에
// 직접 부모 클래스의 생성자를 호출 해야 한다!!
// super(); 사용 불가
super(10); // 부모의 생성자 직접 호출
System.out.println("ClassC 기본생성자");
}
}
public class ClassMain {
public static void main(String[] args) {
ClassC classC = new ClassC();
}
}
/* 실행결과
ClassA 기본생성자
ClassB 생성자 : a=10
ClassC 기본생성자 */
'Java' 카테고리의 다른 글
[Java] 객체 지향 프로그래밍 - 추상화 (Abstraction) (0) | 2024.07.09 |
---|---|
[Java] 객체 지향 프로그래밍 - 다형성 (Polymorphism) (0) | 2024.07.09 |
[Java] 객체 지향 프로그래밍 - 캡슐화 (Encapsulation) (0) | 2024.07.08 |
[Java] 접근 제어자 (Access Modifier) (0) | 2024.07.08 |
[Java] 생성자 (0) | 2024.07.08 |