이번 포스팅은 자바 객체지향프로그래밍의 핵심 개념 중 하나인 상속에 대한 내용이다.
기존 클래스의 필드와 메서드를 새로운 클래스에서 재사용하게 해준다. 상속이라는 단어의 뜻 그대로 기존 클래스의 속성(변수)와 기능(메서드)를 그대로 물려받는 것이다.
몇가지 용어 정리를 하고 들어가보자.
- 부모 클래스(super class) : 상속을 통해 자신의 필드와 메서드를 다른 클래스에 제공하는 클래스
- 자식 클래스(sub class) : 부모 클래스로부터 필드와 메서드를 상속받는 클래스
- extends : 상속을 사용하기 위해 사용되는 키워드. 대상 하나만 선택 가능
장점
- 코드 재사용을 통한 중복 제거를 할 수 있는 장점.
- 부모 클래스를 통한 기능 확장
- 유지보수성
1. 사용
코드를 통해 개념을 알아보자.
public class GasCar {
public void move(){
System.out.println("차를 이동합니다.");
}
public void fillUp(){
System.out.println("주유를 시작합니다.");
}
}
public class ElectricCar {
public void move(){
System.out.println("차를 이동합니다.");
}
public void charge(){
System.out.println("차를 충전합니다.");
}
}
가스차와 전기차는 연료를 충전하는 방식은 다르지만, 이동한다는 특성은 공통부분이라고 할 수 있다.
그렇다면 수소차, 하이브리드차 등 움직일 수 있는 이동 수단에 대한 move()를 해당 클래스에 모두 작성해야할까?
모두 중복되는 코드이므로 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("기름을 주유합니다.");
}
}
전기차와 가스차 클래스는 extends 키워드를 통해 Car클래스를 상속 받았고, move()라는 메서드를 상속받았다고 볼 수 있다. 아래는 사용 예제이다.
public class CarMain {
public static void main(String[] args) {
ElectricCar electricCar = new ElectricCar();
electricCar.move();
electricCar.charge();
GasCar gasCar = new GasCar();
gasCar.move();
gasCar.fillUp();
}
}
/*실행 결과
차를 이동합니다.
차를 충전합니다.
차를 이동합니다.
기름을 주유합니다.
*/
GasCar클래스와 ElectricCar클래스에 move메서드가 없지만, 사용할 수 있는 것을 확인할 수 있다.
이처럼 클래스를 상속받게 되면, 부모 클래스에 있는 필드와 메서드를 자식이 가져다 쓸 수 있다.
만약, Car를 상속받는 모든 클래스에 공통되는 기능을 추가하려면, Car클래스에만 기능을 추가하면 된다.
아래의 코드로 확인해보자.
public class Car {
public void move(){
System.out.println("차를 이동합니다.");
}
public void openDoor(){
System.out.println("문을 엽니다.");
}
}
문을 여는 기능인 openDoor메서드를 추가하였다.
2. 메서드 오버라이딩(Method Overriding)
메서드 오버라이딩 조건
- 메서드 이름이 같아야 한다.
- 메서드 매개변수 타입, 순서, 개수가 같아야 한다.
- 반환 타입이 같아야 한다.
- 상위 클래스의 메서드보다 더 좁은 범위의 접근 제어자를 사용할 수 없다.
- static, final, private키워드가 붙은 메서드는 오버라이딩 할 수 없다.
- 생성자는 오버라이딩 할 수 없다.
부모 클래스의 move메서드를 상속받아서 사용을 할 수 있다. 하지만 자식에서 약간의 변화를 주거나 메서드를 재정의 하고 싶을 수도 있다. 그럴때 사용하는게 메서드 오버라이딩이다.
public class Car {
public void move(){
System.out.println("차를 이동합니다.");
}
public void openDoor(){
System.out.println("문을 엽니다.");
}
}
public class ElectricCar extends Car {
@Override
public void move(){
System.out.println("전기차를 빠르게 이동합니다.");
}
public void charge(){
System.out.println("차를 충전합니다.");
}
}
public class CarMain {
public static void main(String[] args) {
ElectricCar electricCar = new ElectricCar();
electricCar.move();
GasCar gasCar = new GasCar();
gasCar.move();
}
}
/*실행 결과
전기차를 빠르게 이동합니다.
차를 이동합니다.
*/
ElectricCar에서는 Car클래스를 상속받았고, move메서드를 수정하여 재정의 하였다.
@이 붙은 부분은 애노테이션이라고 하며, 주석과 비슷하다. //는 사람이 읽는 주석이라면 @는 프로그램이 읽는 주석이다.
@Override는 자식클래스가 부모 클래스의 메서드를 오버라이드 하는 것임을 프로그램이 인지하게 되는것이다.
애노테이션을 사용하면 프로그램이 사용자의 실수나 조건을 만족시키지 못했을 때 컴파일 에러를 발생시켜준다는 장점이 있다.
3. protected
이전에 포스팅 했던 접근제어자의 종류중 protected는 default와 동일하게 같은 패키지 내에서 접근 가능이라는 점이 있지만, 상속은 허용해준다.
[자바/JAVA] 접근 제어자(Access Modifier)와 캡슐화(Encapsulation)
자바는 public, private와 같은 접근 제어자를 제공한다. 접근 제어자를 사용하면 해당 클래스 외부에서 특정 필드나 메서드에 접근하는 것을 허용하거나 제한할 수 있다. 핵심은 속성과 기능을 외
wook99.tistory.com
코드를 통해 확인하면 이해가 쉽다.
package extends1.access.parent;
public class Parent {
public int publicValue;
protected int protectedValue;
int defaultValue;
private int pritvateValue;
public void publicMethod(){
System.out.println("Parent.publicMethod");
}
protected 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("pritvateValue = " + pritvateValue);
//부모 메서드 안에서 모두 접근 가능
defaultMethod();
privateMethod();
}
}
package extends1.access.child;
import extends1.access.parent.Parent;
public class Child extends Parent {
public void call(){
publicValue = 1;
protectedValue = 1; //상속 관계 or 같은 패키지
// defaultValue = 1; //다른 패키지 접근 불가
// privateValue = 1; // 다른 패키지 접근 불가
publicMethod();
protectedMethod();
// defaultMethod();
// privateMethod();
printParent();
}
Child클래스는 Parent클래스를 상속받고, 서로 다른 패키지에 위치한다.
Child클래스에서 default는 같은 패키지에서만 접근이 가능하고, private는 같은 클래스내에서만 접근 가능하기에 defaultValue, privateValue, defaultMethod(), privateMethod()는 사용할 수 없다.
하지만 같은 패키지 내에서만 접근 가능하고, 상속 관계에서는 다른패키지 접근을 허용하는 protected는 사용할 수 있다.
다음 포스팅은 상속의 중요 개념중 하나인 super를 다뤄보겠음
'JAVA' 카테고리의 다른 글
| [Java] Lombok 이란? (4) | 2024.11.08 |
|---|---|
| [자바/JAVA] 부모 참조(Super, Super Class) (0) | 2024.06.14 |
| [자바/JAVA] final(상수) (3) | 2024.06.13 |
| [자바/JAVA] Static변수와 Static메서드 (0) | 2024.06.13 |
| [자바/JAVA] 자바 메모리 구조와 스택(Stack) (1) | 2024.06.13 |