[객체지향] 클래스 상속

2024. 6. 24. 09:46

✅ 상속(Inheritance)

  • 클래스 상속
    • 새로운 클래스를 정의할 때 이미 구현된 클래스를 상속 받아서 속성이나 기능을 확장하여 클래스를 구현함
    • IS-A 관계를 갖는다
    • 이미 구현된 클래스보다 ‘더 구체적인 기능’을 가진 클래스를 구현해야 할 때 기존 클래스를 상속한다
    • 상속의 목적 중 하나는 코드의 재사용이지만 단순히 코드의 재사용만을 위한 상속을 사용하지 않는다
  • 상속의 특징
    • 상위 클래스는 하위 클래스보다 더 일반적인 개념과 기능을 가짐
    • 하위 클래스는 상위 클래스보다 더 구체적인 개념과 기능을 가짐
    • 상속은 하위 클래스가 상위 클래스의 속성과 기능을 확장 extends 한다는 의미를 갖는다
      하위 클래스는 상위 클래스의 멤버 변수와 메서드에 추가된 멤버 변수(필드)와 기능(메서드)을 갖는다
    • Class B extends A :  ’B클래스가 A클래스를 상속받는다’ 는의미
    • extends 키워드 뒤에 올 수 있는 클래스(상위 클래스)는 단 하나만 올 수 있음
      → 자바는 클래스간 상속시 단일 상속만 지원
      → 다중 상속시 Diamond Problem으로 모호성이 발생 할 수 있기 때문에(글 하단 참고)
  • 상속 예시코드
//상위 클래스
public class Customer {

    private int customId;
    private String customerName;
    protected String customerGrade; 
    int bonusPoint; 
    double bonusRatio; 

    public Customer(){
        customerGrade = "SILVER";
        bonusRatio = 0.01;
    }

    public int calcPrice(int price){
        bonusPoint += price * bonusRatio; 
        return price;
    }

    public String showCustomerInfo(){
        return customerName + "님의 등급은  " + customerGrade + "이며, 보너스 포인트는 " + bonusPoint + "입니다";
    }

    public int getCustomId() {
        return customId;
    }

    public void setCustomId(int customId) {
        this.customId = customId;
    }

    public String getCustomerName() {
        return customerName;
    }

    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }

    public String getCustomerGrade() {
        return customerGrade;
    }

    public void setCustomerGrade(String customerGrade) {
        this.customerGrade = customerGrade;
    }
}
//하위클래스
public class VIPCustomer extends Customer { 

    double saleRatio;
    private String agentID;

    public VIPCustomer(){

        bonusRatio = 0.05;
        saleRatio = 0.1;
        customerGrade = "VIP";
    }

    public String getAgentID() {
        return agentID;
    }

}
//실행클래스
package ch02;

public class CustomerTest {

    public static void main(String[] args) {

        Customer customerLee = new Customer();
        customerLee.setCustomerName("이순신");
        customerLee.setCustomId(10010);
        customerLee.bonusPoint = 1000;
        System.out.println(customerLee.showCustomerInfo());

        VIPCustomer customerKim = new VIPCustomer();
        customerKim.setCustomerName("김유신");
        customerKim.setCustomId(10020);
        customerKim.bonusPoint = 10000;
        System.out.println(customerKim.showCustomerInfo());

    }
}

 

  • 하위 클래스가 생성되는 과정
    • 하위 클래스를 생성하면 상위 클래스가 먼저 생성된다
    • 클래스가 상속받은 경우 하위 클래스 생성자에서는 반드시 상위 클래스의 생성자를 호출한다
    • 상위 클래스의 호출은 super 키워드를 통해 호출
  • super 키워드
    • 하위 클래스에서 가지는 상위 클래스에 대한 참조
    • super() 는 상위 클래스의 기본 생성자를 호출한다
    • 하위 클래스에서 명시적으로 상위 클래스를 호출하지 않으면 super()가 호출된다 → 이때 반드시 상위 클래스의 기본 생성자가 존재해야 하거나 혹은 생성자 코드가 존재하지 않아야 한다
    • 상위 클래스의 기본 생성자가 없고 다른 생성자가 있는 경우 하위 클래스 생성자에서는 super 키워드를
      이용하여 반드시 명시적으로 상위 클래스의 생성자를 호출해야 한다
    • super 키워드는 생성된 상위 클래스 인스턴스 참조 값을 가지므로 super를 이용하여 상위 클래스의 메서드나 멤버 변수에 접근할 수 있다
  • super 키워드 예시코드
//상위클래스
public class Customer {
        protected int customId;
        protected String customerName;
        protected String customerGrade;
        int bonusPoint;
        double bonusRatio;

    public Customer(int customId, String customerName){
        this.customId = customId;
        this.customerName = customerName;

        customerGrade = "SILVER";
        bonusRatio = 0.01;

    }

        public int calcPrice(int price){
            bonusPoint += price * bonusRatio;
            return price;
        }

        public String showCustomerInfo(){
            return customerName + "님의 등급은  " + customerGrade + "이며, 보너스 포인트는 " + bonusPoint + "입니다";
        }

        public int getCustomId() {
            return customId;
        }

        public void setCustomId(int customId) {
            this.customId = customId;
        }

        public String getCustomerName() {
            return customerName;
        }

        public void setCustomerName(String customerName) {
            this.customerName = customerName;
        }

        public String getCustomerGrade() {
            return customerGrade;
        }

        public void setCustomerGrade(String customerGrade) {
            this.customerGrade = customerGrade;
        }

}
//하위클래스
public class VIPCustomer extends Customer {

        double saleRatio;
        private String agentID;

        public VIPCustomer(int customerId, String customerName){

            super(customerId, customerName); 
            customerGrade ="VIP";
            bonusRatio = 0.05;
            saleRatio = 0.1;

        }

        public String getAgentID() {
            return agentID;
        }

    @Override
    public int calcPrice(int price) {
        bonusPoint += (price*bonusRatio);
        price -= (int)(price*saleRatio);
        return super.calcPrice(price);
    }
}

//실행 클래스
public class CustomerTest {

    public static void main(String[] args) {

            Customer customerLee = new Customer(10010, "이순신");
            customerLee.bonusPoint = 1000;
            int price = customerLee.calcPrice(1000);
            System.out.println(customerLee.showCustomerInfo() + price);

            VIPCustomer customerKim = new VIPCustomer(10020, "김유신");
            customerKim.bonusPoint = 10000;
            price = customerKim.calcPrice(1000);
            System.out.println(customerKim.showCustomerInfo() + price);

            Customer vc = new VIPCustomer(12345, "noname"); 
            int result = vc.calcPrice(1000);
            System.out.println(result); // VIPCustomer의 calcPrice() 오버라이드 매서드가 호출
        }

}

 

  • 상속에서 인스턴스 메모리 상태
    • 항상 상위 클래스의 인스턴스가 먼저 생성된 후 하위 클래스 인스턴스가 생성된다

 

✅ Diamond Problem 이란? (참고)

✅ 다이아몬드 문제란? 
해당 그림과 같이 다중 상속을 허용하게 GrandFather의 메서드를 구현한 FatherA와 FatherB를 상속받는 Son에서 해당 메서드를 호출할 때 어떤 메서드를 호출해야하는지 충돌하는 문제가 생긴다.
예로들면 GrandFather의 callI()이란 메서드를 FatherA와 FatherB가 구현하고 Son에서 call 메서드를 호출 할 때 어떤 메서드를 호출해야하는지 모호성이 발생하는데 이를 Diamond Problem이라고 한다.
따라서 클래스의 상속은 다중상속을 지원하지 않는다

 

'JAVA > 객체지향' 카테고리의 다른 글

[객체지향] 인터페이스  (0) 2024.07.08
[객체지향] 다형성  (0) 2024.06.26
[객체지향] Static  (0) 2024.06.26
[객체지향] 업캐스팅 다운캐스팅  (0) 2024.06.25
[객체지향] this  (1) 2024.06.25

BELATED ARTICLES

more