상속은 기존 클래스의 필드와 메서드를 새로운 클래스에서 재사용하게 해준다.
이름 그대로 기존 클래스의 속성과 기능을 그대로 물려받은 것이다.
상속을 사용할려면, extends키워드를 사용하면 된다. 그리고 extends 대상은 하나만 선택할 수 있다.
용여 정리
부모 클래스: 상속을 통해 자신의 필드와 메서드를 다른 클래스에 제공하는 클래스
자식 클래스: 부모 클래스로부터 필드와 메서드를 상속받는 클래스
package extend1.ex2;
public class Car {
public void move() {
System.out.println("차를 이동합니다.");
}
}
package extend1.ex2;
public class ElectricCar extends Car{
public void charge() {
System.out.println("충전합니다");
}
}
package extend1.ex2;
public class GasCar extends Car{
public void fillup() {
System.out.println("fill up GasCar");
}
}
extends 를 통해서Car을 상속 받을 수 있다
package extend1.ex2;
import extend1.ElectricCar;
import extend1.Gascar;
public class CarMain {
public static void main(String[] args) {
extend1.ex2.ElectricCar car= new extend1.ex2.ElectricCar();
car.move();
car.charge();
GasCar gascar = new GasCar();
gascar.move();
gascar.fillup();
}
}
결과값
차를 이동합니다.
충전합니다
차를 이동합니다.
fill up GasCar
단일 상속
참고로 자바는 다중 상속을 지원하지 않는다. 그래서 extend 대상은 하나만 선택할 수 있다.
부모를 하나만 선택할 수 있다는 뜻이다.
상속과 메모리 구조
메모리에는 자식과 부모 메서드를 두 개 다 올린다.
electricCar.charge()` 를 호출하면 참조값을 확인해서 `x001.charge()` 를 호출한다.
따라서 `x001` 을 찾아서 `charge()` 를 호출하면 되는 것이다. 그런데 상속 관계의 경우에는 내부에 부모와 자식이 모두 존재한다.
이때 부모인 `Car` 를 통해서 `charge()` 를 찾을지 아니면 `ElectricCar` 를 통해서 `charge()` 를 찾을지 선택해야 한다.
이때는 **호출하는 변수의 타입(클래스)을 기준으로 선택**한다. `
electricCar` 변수의 타입이 `ElectricCar` 이므로 인스턴스 내부에 같은 타입인 `ElectricCar` 를 통해서 `charge()` 를 호출한다
그런데 `ElectricCar` 에는 `move()` 메서드가 없다.
상속 관계에서는 자식 타입에 해당 기능이 없으면 부모 타입으 로 올라가서 찾는다.
이 경우 `ElectricCar` 의 부모인 `Car` 로 올라가서 `move()` 를 찾는다.
부모인 `Car` 에 `move()` 가 있으므로 부모에 있는 `move()` 메서드를 호출한다.
상속과 접근 제어
`+` : public
`#` : protected `~` : default
`-` : private
- **접근 제어자의 종류**
`private` : 모든 외부 호출을 막는다.
`default` (package-private): 같은 패키지안에서 호출은 허용한다.
`protected` : 같은 패키지안에서 호출은 허용한다. 패키지가 달라도 상속 관계의 호출은 허용한다.
`public` : 모든 외부 호출을 허용한다.
순서대로 `private` 이 가장 많이 차단하고, `public` 이 가장 많이 허용한다. `private -> default -> protected -> public`
package extend1.access.parent;
public class Parent {
public int publicValue;
protected int protectedValue;
int defaultValue;
private int privateValue;
public void publicMethod() {
System.out.println("Parent.publicMethod");
}
public void protectedMethod() {
System.out.println("Parent.protectedMethod");
}
void defaultMethod() {
System.out.println("Parent.defaultMethod");
}
private void privateMethod() {
System.out.println("Parent.privateMethod");
}
public void printParent() {
System.out.println("==Parent 메서드안==");
System.out.println("publicValue: " + publicValue);
System.out.println("protectedValue: " + protectedValue);
System.out.println("defaultValue: " + defaultValue);
System.out.println("privateValue: " + privateValue);
//부모메서드 안에서 모두 접근 가능
defaultMethod();
privateMethod();
}
}
package extend1.access.child;
import extend1.access.parent.Parent;
public class Child extends Parent {
public void call() {
//private int privateValue; 부모에서 선언한 변수값
publicValue = 1;
protectedValue = 1; //상속관계 or 같은 패키지. protected int protectedValue;
// defaultValue = 1; int defaultValue; 로만 선언하면 다른 패키지에 있기 때문에 오류가 난다.
// privateValue = 1; // private int privateValue; 이기 때문에 접근 오류뜬다
publicMethod(); // public. 이기 때문에 호출 가능
protectedMethod(); // 상속 과 같은 패키지
printParent();
// public void printParent() 로 호출한다음 가져오기 때문에, 가능한다.
}
}
package extend1.access;
import extend1.access.child.Child;
public class ExtendsAccessMain {
public static void main(String[] args) {
Child child = new Child();
child.call();
}
}
출력값
Parent.publicMethod
Parent.protectedMethod
==Parent 메서드안==
publicValue: 1
protectedValue: 1
defaultValue: 0
privateValue: 0
Parent.defaultMethod
Parent.privateMethod
parent 와 child 두 부분으로 나눠서 저장을 하며, 부모 입장에서 보면 외부에서 호출된 것이다.
'JAVA' 카테고리의 다른 글
[Java] 다형성 (0) | 2024.11.01 |
---|---|
[Java] 상속 문제와 풀이 (0) | 2024.11.01 |
[Java] Static 메서드1 (1) | 2024.10.27 |
[Java] Static (0) | 2024.10.27 |
[Java] 메모리구조 (2) | 2024.10.27 |