Java

[JAVA] 상속

HSRyuuu 2023. 5. 17. 13:00

상속 (Inheritance)

  • 새로운 클래스를 정의할 때 이미 구현된 클래스를 상속(inheritance) 받아서 속성이나 기능을 확장하여 구현한다.
  • 기존의 클래스보다 더 구체적인 기능을 가진 클래스를 구현해야 할 때 상속을 이용함.

기본 문법 

(Parent 클래스를 상속받은 Child 클래스)

  • extends 키워드 뒤에는 단 하나의 클래스만 올 수 있음 (단일 상속)
class Child extends Parent{
	//필드
	//메서드
}
  • 상위 클래스 : 하위 클래스보다 더 일반적인 개념과 기능을 가짐
  • 하위클래스 : 상위 클래스보다 더 구체적인 개념과 기능을 가짐
  • 하위 클래스가 상위 클래스의 속성과 기능을 확장(extends)

자식클래스 Child에서는 부모클래스 Parent의 메서드와 멤버변수 등을 호출해서 사용할 수 있음.

그러나, private, default 변수는 자식클래스에서 접근할 수 없다.


this와 super 키워드

  • this : 객체 자기 자신을 의미하는 키워드
  • super : 상위 객체를 의미하는 키워드

super

부모 클래스와 자식 클래스의 멤버변수 이름이 같을 때 구분하는 키워드

super()

부모 클래스의 생성자를 호출한다.

해당 메서드는 자식 클래스의 생성자 안에 들어가며, 무조건 자식 클래스의 생성자의 첫줄에 들어가야 한다.


예제

public class Vehicle {
    public String name = "vehicle";
    public int maxSpeed;
    public int capacity;

    public Vehicle() {
        System.out.println("Vehicle 생성자 호출");
    }
    
    public void print(){
        System.out.println("name = " + name);
        System.out.println("maxSpeed = " + maxSpeed);
        System.out.println("capacity = " + capacity);
    }
}
public class Car extends Vehicle {
    public String name = "myCar";
    public String displacement; //배기량

    public Car() {
        super(); //부모 클래스의 생성자 호출
        System.out.println("Car 생성자 호출");

    }

    public void print(){
    //super 키워드 : 부모 클래스의 name을 가리킨다.
        System.out.println("(Vehicle) name = " + super.name); 
        System.out.println("maxSpeed = " + maxSpeed);
        System.out.println("capacity = " + capacity);

        System.out.println("displacement = " + displacement);
        //this 키워드 : 지금 이 클래스의 name을 가리킨다.
        System.out.println("(Car) name = " + this.name);
    }
}
public class VehicleTest {
    public static void main(String[] args) {
        Car myCar = new Car();
        myCar.maxSpeed = 200;
        myCar.capacity = 4;
        myCar.displacement = "2000cc";
        myCar.print();
    }
}

(출력)

Vehicle 생성자 호출
Car 생성자 호출
(Vehicle) name = vehicle
maxSpeed = 200
capacity = 4
displacement = 2000cc
(Car) name = myCar

부모 클래스의 생성자를 호출하는 super() 는 항상 자식 클래스 생성자의 첫줄에 써줘야 한다.

또한, 부모 클래스와 자식클래스가 같은 이름의 멤버변수를 가질 경우, super, this로 구분할 수 있다.


super()를 이용해서 부모 생성자에 파라미터를 넘길 수도 있다.

public Vehicle(int maxSpeed, int capacity) {
    this.maxSpeed = maxSpeed;
    this.capacity = capacity;
}
public Car(int maxSpeed, int capacity, String displacement) {
    super(maxSpeed, capacity);
    this.displacement = displacement;
}

이렇게 super()에 파라미터를 넘겨서 부모 클래스 생성자에 값을 전달할 수 있다.


Overriding

부모클래스의 메서드를 자식클래스에서 상속받아서 재정의 하는것.

메서드의 선언부는 부모 클래스의 메서드와 동일해야 한다. ( 매개변수(파라미터)나 메서드 이름 등이 동일해야 함. )

overriding 예제

더보기

간단하게 자동차의 종류를 출력하는 printType()이라는 메서드를 만들었다.

Car 클래스

class Car{
    Car(){}
    public void printType(){
        System.out.println("자동차 입니다.");
    }
}

Sedan클래스

Sedan클래스는 printType을 overriding 하여 "세단입니다."를 출력하도록 했다.

class Sedan extends Car{
    @Override
    public void printType() {
        System.out.println("세단 입니다.");
    }
}

SUV 클래스

SUV 클래스는 printType을 overriding 하여 "SUV입니다."를 출력하도록 하고, 추가로 super의 printType메서드도 실행하도록 했다.

class SUV extends Car{
    @Override
    public void printType() {
        super.printType();
        System.out.println("SUV 입니다.");
    }
}

Truck

Truck 클래스는 상속만 받고 아무것도 overriding 하지 않았다.

class Truck extends Car{
}

테스트코드와 출력 결과

public static void main(String[] args) {
        System.out.println("=== Sedan ===");
        Sedan sedan = new Sedan();
        sedan.printType();
        System.out.println("=== SUV ===");
        SUV suv = new SUV();
        suv.printType();
        System.out.println("=== Truck ===");
        Truck truck = new Truck();
        truck.printType();
    }
=== Sedan ===
세단입니다.
=== SUV ===
자동차입니다.
SUV입니다.
=== Truck ===
자동차입니다.

overriding을 한 경우에는 overriding 한 메서드만 출력되고, overriding 하지 않은 경우에는 부모클래스의 메서드가 그대로 출력되는 것을 볼 수 있다.

추가로 super 키워드를 이용하여 부모클래스의 메서드도 사용할 수 있다.


형 변환 (업캐스팅과 다운캐스팅) 

  • 상위 클래스 : Customer(int customerID, String CustomerName)
  • 하위 클래스 : VIPCustomer(int customerID, String CustomerName)

2-1. 업캐스팅  

Customer vc = new VIPCustomer();

2-2. 다운캐스팅

VIPCustomer vCustomer = (VIPCustomer)vc;

2-3. instanceof를 사용하여 확인

원래 인스턴스의 형이 맞는지 체크하는 키워드

  • 다운캐스팅 시 잘못된 형으로 변환되어 생기는 오류를 방지하기 위함 
//업캐스팅
Customer vipMan = new VIPCustomer();
//다시 다운캐스팅
if(vipMan instanceof VIPCustomer){
	VIPCustomer vc = (VIPCustomer)vipMan;
}else System.out.println("error");

예제

Car 클래스

  • Car 클래스는 carName, carNum, type, price 속성을 갖고 있다.
  • CarClass를 생성할 때는 이름과 번호를 입력받고, type은 none, 가격은 0으로 초기된다.
  • printType 메서드는 자동차에 대한 정보를 출력해 준다. 
class Car{
    String carName;
    int carNum;
    String type;
    int price;
    Car(){}

    public Car(String carName, int carNum) {
        this.carName = carName;
        this.carNum = carNum;
        type = "none";
        price = 0;
    }

    public void printType(){
        System.out.println("자동차 종류는 ["+type+"]입니다.");
        System.out.println("carName = " + carName);
        System.out.println("carNum = " + carNum);
        System.out.println("type = " + type);
        System.out.println("price = " + price);
    }
}

Sedan extends Car 클래스

  • Car을 상속받은 Sedan 클래스이다.
  • Sedan클래스는 생성할 때 이름, 번호, 가격을 입력받는다. 
  • 생성자에서 super()을 이용해 부모클래스의 생성자를 이용하고, 추가로 type과 price를 설정해 준다.
class Sedan extends Car{
    public Sedan(String carName, int carNum, int price){
        super(carName,carNum);
        this.type="sedan";
        this.price = price;
    }
}

Truck extends Car 클래스

  • Car을 상속받은 Truck 클래스이다.
  • Truck 클래스는 생성할 때 이름, 번호, 가격을 입력받고 추가로 적재량 도 입력받는다.
  • printType메서드에서는 super키워드를 이용해서 부모클래스의 메서드를 호출하고, 추가로 적재량을 출력한다.
class Truck extends Car{
    int load;
    public Truck(String carName, int carNum, int price,int load){
        super(carName,carNum);
        this.type = "truck";
        this.price = price;
        this.load = load;
    }

    @Override
    public void printType() {
        super.printType();
        System.out.println("적재량 = " + load+"t");
    }
}

테스트 코드, 출력 결과

Sedan클래스 객체를 생성할 때 Car클래스로 업캐스팅 하여 Car 타입으로 생성할 수 있다.

 public static void main(String[] args) {
        System.out.println("=== Sedan ===");
        Sedan sedan = new Sedan("mysedan",1234,2000);
        sedan.printType();
        System.out.println("=== Truck ===");
        Truck truck = new Truck("myTruck", 5678, 4000, 2);
        truck.printType();
        System.out.println("=== 업캐스팅 ===");
        Car myCar = new Sedan("mysedan2",1313,1500);
        myCar.printType();
    }
=== Sedan ===
자동차 종류는 [sedan]입니다.
carName = mysedan
carNum = 1234
type = sedan
price = 2000
=== Truck ===
자동차 종류는 [truck]입니다.
carName = myTruck
carNum = 5678
type = truck
price = 4000
적재량 = 2t
=== 업캐스팅 ===
자동차 종류는 [sedan]입니다.
carName = mysedan2
carNum = 1313
type = sedan
price = 1500
반응형