자바 - 상속과 다형성

신범철·2022년 1월 1일
0

자바

목록 보기
3/17

머리말

이글은 자바를 빠르게 끝내기 위해 내가 헷갈리는 부분만을 정리해논 글입니다. Do it! 자바 프로그래밍 입문을 정리하지만 내용을 많이 건너뜀

상속이란?

객체 지향 프로그래밍(OOP) 특징

  • 상속(inheritance)
  • 다형성
  • 추상화
  • 캡슐화


B클래스가 A클래스에서 상속받는다.(화살표가 A클래스를 가르키는데 이것을 헷갈리지 말것)

상속을 사용하는 경우

상위 클래스는 하위 클래스보다 일반적인 개념과 기능을 가지고 하위 클래스는 상위 클래스보다 구체적인 개념과 기능을 가진다.
포유류 <- 사람의 경우에는 포유류는 더 포괄적인 개념으로 사람뿐만 아니라 침팬지, 고릴라, 팬더 등 다른 포유류들로 분화될 수 있는 것 같이 일반적인 상위클래스는 구체적인 여러 하위 클래스들로 세분화 될 수 있다.

Class Mammal {
///코드
}
Class Human extends Mammal {
///코드
}

상속을 이용한 고객관리 프로그램

package inheritance;

public class Customer {
    private int customerID;
    private String customerName;
    private 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 + "입니다.";
    }

}

Customer클래스를 상속받아 VIPCustomer클래스를 만들어보면

package inheritance;

public class Customer {
    protected int customerID;
    protected 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 getCustomerID() {
        return customerID;
    }

    public void setCustomerID(int customerID) {
        this.customerID = customerID;
    }

    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;
    }

}

기존 customer클래스의 멤버변수중 private로 되어 있던 것들은 외부 클래스에서 사용이 불가능했으므로 protected를 사용하여 상속받은 클래스에서는 사용할수 있도록 해주었다. 그리고 다른 외부클래스에서는 get, set를 이용하여 사용하도록 수정하였다.

package inheritance;

public class VIPCustomer extends Customer{
    private int agentID;
    double saleRatio;

    public VIPCustomer(){
        customerGrade = "VIP";
        bonusRatio = 0.05;
        saleRatio = 0.1;
    }

    public int getAgentID(){
        return agentID;
    }
}
package inheritance;

import java.sql.SQLOutput;

public class CustomerTest1 {
    public static void main(String[] args){
        Customer customerLee = new Customer();
        customerLee.setCustomerID(10010);
        customerLee.setCustomerName("이순신");
        customerLee.bonusPoint =1000;
        System.out.println(customerLee.showCustomerInfo());


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

접근제어자(access modifier)

상속에서 클래스 생성과 형 변환

  • 상속관계에서 하위 클래스가 생성 될 때 상위 클래스가 먼저 생성된다. 왜 why 하위 클래스에서 상위 클래스의 변수나 메서드를 사용할 수 있는데 이를 위해서는 상위 클래스를 생성할 필요가 있기 때문이다.
  • 생성되는 순서 상위클래스 생성자 -> 하위 클래스 생성자

부모를 부르는 예약어, super

super예약어는 하위 클래스에서 상위 클래스로 접근할 때 사용
super예약어 역시 디폴트로 자동으로 호출된다.
super()를 호출하면 상위 클래스의 디폴트 생성자가 호출된다.

BUT 만약에 상위클래스의 디폴트 생성자가 없고 생성자에 매겨변수가 있다면
반드시 하위클래스에서 super(상위클래스 생성자호출)를 통해 상위클래스의 생성자를 호출해 주어야한다.

상위 클래스의 멤버 변수나 메서드를 참조하는 super()

상위 클래스에 선언한 멤버변수나 메서드를 하위 클래스에서 참조할 때도 super를 사용함
this를 사용하여 자신의 멤버에 접근했던 것과 비슷하다.

예를 들어 VIPCustomer클래스의 showVIPInfo()메서드에서 상위 클래스 showCustomerInfo()메서드를 참조해 담당 상담원 아이디를 추가로 출력한다면

    public String showVIPInfo(){
        return super.showCustomerInfo() + "담당 상담원 아이디는 " +
                agentID + "입니다.";
    }

이런식으로 구현이 가능하다. 다만 위 예제는 super를 사용하지 않아도 showCustomerInfo메서드를 사용할 수 있지만
하위 클래스가 상위클래스와 동일한 이름의 메서드를 구현하는 경우(메서드 오버라이딩) super.showCustomerInfo()를 사용해야한다.

상위 클래스로의 묵시적 형 변환(업캐스팅)

VIPCustomer는 VIPCustomer형이면서 동시에 Customer형이기도합니다.
따라서 VIPCustomer 클래스로 인스턴스를 생성할 때 이 인스턴스의 자료형을 Customer형으로 클래스 형 변환하여 선언할 수 있다.
하지만 반대로 Customer로 인스턴스를 생성할 때 VIPCustomer형으로 선언을 할수 없다.
왜냐하면 상위 클래스인 Customer은 VIPCustomer클래스의 기능을 다 가지고 있지 않기 때문이다.

형 변환된 vc가 가리키는 것

Customer vc = new VIPCustomer();에서 형 변환된 vc가 가르키는 것은?
클래스가 형 변환이 되었을 때는 선언한 클래스형에 기반하여 멤버변수와 메서드에 접근 가능하다.
고로 Customer 클래스의 멤버변수와 메서드에만 접근이 가능하다.

메서드 오버라이딩

상위 클래스 메서드 재정의하기 = 오버라이딩(overriding)

상위 클래스에서 정의된 메서드의 구현 내용이 하위 클래스에서 구현할 내용과 맞지 않는 경우 하위 클래스에서 동일한 이름의 메서드를 재정의 할 수 있고 그것을 오버라이딩이라고한다.

오버라이딩의 조건 : 반환형, 메서드이름, 매겨변수 개수, 매개변수 자료형이 반드시 같아야한다.

package inheritance;

public class VIPCustomer extends Customer{
    private int agentID;
    double saleRatio;

    public VIPCustomer(){
        customerGrade = "VIP";
        bonusRatio = 0.05;
        saleRatio = 0.1;
    }

    public int getAgentID(){
        return agentID;
    }

    public String showVIPInfo(){
        return super.showCustomerInfo() + "담당 상담원 아이디는 " +
                agentID + "입니다.";
    }

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

@Overide 적고 CTRL + SPACE하면 오버라이딩하고 싶은 메서드의 예제가 나옴

형변환과 오버라이딩 메서드 호출

Customer vc = new VIPCustomer();
vc.calcPrice(10000);

  • 위의 코드에서 calcPrice()메서드는 Customer클래스의 메서드가 호출될 것이라고 생각하기 쉽지만 VIPCustomer클래스의 메서드가 호출됨
  • Java에서는 항상 인스턴스의 메서드가 호출되고 이것을 가상 메서드 기법이라고 한다.

가상 메서드(virtual method)

함수 혹은 메서드는 이름이 그 자체로 주소역할을 하기 때문에 같은 이름을 가진 다른 메서드가 존재할 수 없지만 override를 하는 경우 같은 이름의 다른 주소값을 가진 메서드가 재정의 되기 때문에 같은 이름의 다른 기능을 하는 메서드를 가질 수 잇다.
이처럼 override를 할 수 있는 메서드를 가상메서드라고 한다.

다형성(ploymorphism)

하나의 코드가 여러 자료형으로 구현되어 실현되는 것을 뜻하며 이는 같은 코드에서 여러 실행 결과가 나올 수 있는 것을 의미함
OOP의 유연성, 재활용성, 유지보수성에 기본이 되는 특징이다.

다형성의 장점

  • 다형성을 이용하여 다양한 여러 클래스를 하나의 자료형(상위클래스)으로 선언하거나 형변환 하여 각 클래스가 동일한 메서드를 오버라이딩 한 경우, 하나의 코드가 다양한 구현을 실행 할 수 있습니다.
  • 다형성을 통해서 유사한 클래스가 추가되는 경우 유지보수에 용이하고 각 자료형 마다 다른 메서드를 호출하지 않으므로 코드에서 많은 if문이 사라지는 장점이 있다.

다운캐스팅과 instanceof

하위 클래스로 형 변환, 다운 캐스팅

묵시적으로 상위 클래스 형변환된 인스턴스가 원래 자료형(하위클래스)으로 변환되어야 할 때 다운캐스팅이라고 한다.
하위 클래스로의 형변환은 명시적으로 되어야 한다.

Customer vc = new VIPCustomer();//묵시적 = 업캐스팅
VIPCustomer vCustomer = (VIPCustomer)vc;//명시적 = 다운캐스팅
profile
https://github.com/beombu

0개의 댓글