Do it! 자바 프로그래밍 입문 / 8장 상속

2023. 1. 3. 03:31·Programming Language/자바(JAVA)

8.1 상속이란?

클래스 B가 클래스 A를 상속 받는 것은 A의 내용들을 B가 상속 받는 다는 것을 의미한다.
아래처럼 클래스를 선언할 때 extends를 이용해서 상속받는다.

class B extends A
{
}

protected 예약어 : 외부에선 접근이 불가능하면서 상속받은 클래스에서는 접근이 가능하게 하는 예약어
|public|외부에서 접근 가능|
|protected|자기 자신, 상속 클래스에서만 접근 가능|
|private|자기 자신만 접근 가능|

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

하위 클래스가 생성되는 과정

하위 클래스 생성 : 상위 클래스 디폴트 생성자 호출 -> 하위 클래스 생성자 호출
super() : 상위 클래스에 접근할 때 사용하는 예약어(매개변수가 있는 생성자를 호출할 수도 있음)
super 예약어를 작성하지 않는다면 자동으로 super()이 실행돼서 디폴트 생성자가 호출되는 것

class VIP()
{
    public VIP()
    {
        super(int ID, String Name) // 상위 클래스의 디폴트 생성자가 아닌 매개변수가 있는 생성자를 호출
    }
}

아래처럼 super 예약어를 이용해서 상위 클래스의 멤버에도 접근할 수 있음

class VIP()
{
    public String showVIPInfo()
    {
        return super.showCustomerInfo() // 상위 클래스인 Customer 클래스의 멤버 함수 showCustomerInfo() 함수를 호출
    }
}

상위 클래스로 묵시적 클래스 형 변환

"하위 클래스인 VIP 클래스를 상위 클래스인 Customer 클래스"로 형 변환할 수 있음
형 변환 하게 되면 상위 클래스의 멤버 변수와 메소드만 사용 가능하다.
(힙 메모리에 상위, 하위 클래스의 변수 모두 생성은 되지만 사용은 상위 클래스 멤버 변수만 가능함)
But, 그 반대인 상위 "

클래스 -> 하위 클래스

"는 불가능하다

Customer vc = new VIP() // VIP 클래스를 생성했지만 Customer 클래스로 형변환 했기 때문에 Customer 멤버 변수와 메소드에 접근 가능 

8.3 메서드 오버라이딩

상위 클래스 메소드(함수) 재정의

메소드 오버라이딩 : 상위 클래스에 정의된 메소드를 하위 클래스에 재정의하는 것
하위 클래스에 재정의 할 때 반환형, 메소드 이름, 매개변수 개수, 매개변수 자료형이 상위 클래스의 메소드와 같아야 한다. 만약 넷 중 하나라도 다르면 오버라이딩이 아닌 아예 다른 함수로 본다.

묵시적 클래스 형 변환과 메소드(함수) 재정의(가상 메소드)

만약 형 변환을 한 인스턴스의 함수를 호출할 때 호출하는 함수가 재정의된 함수인 경우 어떤 함수가 호출될까?
-> 재정의한 함수를 호출할 경우 생성된 인스턴스의 메소드를 호출하게 된다.(new 클래스 <- 얘의 메소드 호출한다는 의미)

Customer vc = new VIP("10030", "나몰라", 2000)
vc.calcPrice(10000); // VIP의 calcPrice() 메소드를 호출

형 변환한 객체의 경우
멤버 변수는 힙 메모리에 특정 객체만의 멤버 변수가 생성되지만
멤버 메소드는 특정 객체의 멤버 메소드가 생성되는 것이 아닌 메소드가 호출될 때 메소드 테이블의 메소드 주소를 참조해서 해당 메소드를 호출한다.
즉, 인스턴스를 생성할 때 변수는 특정 인스턴스 전용 변수 생성, 메소드는 따로 생성하지 X

8.4 다형성

다형성 : 가상 메소드를 이용하여 하나의 코드에서 여러 실행 결과나 나오는 것

class Animal{
    public void move()
    {
        System.out.println("동물이 움직입니다.");
    }
}

class Human extends Animal{
    public void move()
    {
        System.out.println("사람이 두 발로 걷습니다. ");
    }

    public void readBook()
    {
        System.out.println("사람이 책을 읽습니다. ");
    }
}

class Tiger extends Animal{
    public void move()
    {
        System.out.println("호랑이가 네 발로 뜁니다. ");
    }

    public void hunting() 
    {
        System.out.println("호랑이가 사냥을 합니다. ");
    }
}

class Eagle extends Animal{
    public void move()
    {
        System.out.println("독수리가 하늘을 납니다 ");
    }

    public void flying() 
    {
        System.out.print("독수리가 날개를 쭉 펴고 멀리 날아갑니다");
    }
}

public class AnimalTest1 {

     public static void main(String[] args) {
          AnimalTest1 aTest = new AnimalTest1();
          aTest.moveAnimal(new Human());
          aTest.moveAnimal(new Tiger());
          aTest.moveAnimal(new Eagle());
     }

     public void moveAnimal(Animal animal) {   // 매개 변수의 자료형이 상위 클래스
          animal.move(); }                     // 재정의 된 메서드 호출
}

위의 animal.move()에서 각 클래스의 재정의된 move 메소드가 호출된다.
결국 여러 클래스 자료형을 사용하지 않고 Animal 자료형 하나로 여러 클래스의 재정의된 메소드를 간편하게 사용할 수 있다는 것이 장점이다.

8.5 다형성 활용하기

배열에 상위, 하위 클래스 인스턴스를 넣어서 관리

상위 클래스 자료형으로 배열을 선언한다.
-> 배열에 인스턴스를 추가하면 자동으로 상위 클래스 자료형으로 묵시적 형 변환이 된다.

public class CustomerTest {

    public static void main(String[] args) {

        // 상위 클래스인 Customer 자료형으로 배열을 선언한다.
        ArrayList<Customer> customerList = new ArrayList<Customer>();

        // 상위, 하위 클래스의 인스턴스를 배열에 추가하면 상위 클래스 자료형으로 형 변환이 된다.
        Customer customerLee = new Customer(10010, "이순신");
        Customer customerShin = new Customer(10020, "신사임당");
        Customer customerHong = new GoldCustomer(10030, "홍길동");
        Customer customerYul = new GoldCustomer(10040, "이율곡");
        Customer customerKim = new VIPCustomer(10050, "김유신", 12345);

        // 여기선 미리 형 변환을 하고 add() 했지만 형 변환을 안하고 하위 클래스 인스턴스를 넣어도 자동으로 묵시적 형 변환이 된다.
        customerList.add(customerLee);
        customerList.add(customerShin);
        customerList.add(customerHong);
        customerList.add(customerYul);
        customerList.add(customerKim);

        System.out.println("====== 고객 정보 출력 =======");

        for( Customer customer : customerList){
            System.out.println(customer.showCustomerInfo());
        }

        System.out.println("====== 할인율과 보너스 포인트 계산 =======");

        int price = 10000;
        for( Customer customer : customerList){
            int cost = customer.calcPrice(price);
            System.out.println(customer.getCustomerName() +" 님이 " +  + cost + "원 지불하셨습니다.");
            System.out.println(customer.getCustomerName() +" 님의 현재 보너스 포인트는 " + customer.bonusPoint + "점입니다.");
        }
    }
}

상속은 왜 사용할까?

상속을 사용하지 않고 상위 클래스(Customer 클래스)에 Gold, VIP 내용을 추가해서 코드를 작성할 수도 있다.

if(customerGrade == "VIP") {}
else if(customerGrade == "GOLD") {}
else if(customerGrade == "SILVER") {}

이런 조건문을 필요한 함수마다 집어 넣으면 가능하다.
하지만 이런식으로 하면 코드가 너무 복잡하고 가독성이 안좋아져서 상속을 이용해 가독성 좋은 코드를 만드는 것이다.

상속은 언제 사용할까?

상속은 'IS-A 관계'일 때 사용한다.
IS-A 관계 : '사람은 포유류다'와 같이 상위 클래스가 하위 클래스를 포괄하는 경우(특정 개념(포유류)을 구체화(사람) 하는 경우)

단순히 코드 재활용을 목적으로 사용하지 않는다.('HAS-A 관계'일 때는 사용하지 않는다)
HAS-A 관계 : '학생이 과목을 듣는다.'와 같이 (특정 클래스(학생)이 다른 클래스(과목)을 소유하고 있는 경우)

8.6 다운 캐스팅과 instanceof

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

다운 캐스팅 : 상위 클래스로 형 변환을 한 인스턴스를 다시 하위 클래스 자료형으로 형 변환하는 경우
(상위 클래스 자료형 -> 하위 클래스 자료형)
.

instanceof

다운 캐스팅을 하기 전에 상위 클래스를 상속받은 여러 하위 클래스 중 어떤 하위 클래스인지 확인하는 예약어

'상위 클래스 -> 하위 클래스' 형 변환은 자료형을 명시적으로 써줘야 형 변환이 된다.

class Shape{
    void draw()
    {
        System.out.println("draw Shape");
    }
}

class Circle extends Shape{
    void draw()
    {
        System.out.println("draw Circle");
    }
    void circle()
    {
        System.out.println("원 입니다.");
    }
}

class Rectangle extends Shape{
    void draw()
    {
        System.out.println("draw Rectangle");
    }
    void rectangle()
    {
        System.out.println("사각형 입니다.");
    }
}

class Triangle extends Shape{
    void draw()
    {
        System.out.println("draw Triangle");
    }
    void triangle()
    {
        System.out.println("삼각형 입니다.");
    }
}


public class ShapeTest {

    ArrayList<Shape> sList = new ArrayList<Shape>();

    public static void main(String[] args) {

        ShapeTest sTest = new ShapeTest();
        sTest.addShape();
        System.out.println("원래 타입으로 다운 캐스팅 ");
        sTest.testCasting();

    }

    public void addShape()
    {
        sList.add(new Circle());    //ArrayList 에 추가되면서 Shape 타입으로 형 변환
        sList.add(new Rectangle());
        sList.add(new Triangle());

        for( Shape s : sList){     // 모두 Shape 타입으로 꺼내서 draw 호출하면
            s.draw();              // 오버라이딩된 함수가 호출 됨
        }
    }

    public void testCasting()
    {
        for(int i=0; i<sList.size(); i++){  //모든 배열 항목들을 하나씩 돌면서

            Shape s = sList.get(i);        // 일단 Shape 타입으로 가져옴
            if(s instanceof Circle){       //Circle 이면
                Circle c = (Circle)s;      //Circle 로 형변환
                c.circle();
            }
            else if(s instanceof Rectangle){  
                Rectangle r = (Rectangle)s;
                r.rectangle();
            }
            else if(s instanceof Triangle){
                Triangle t = (Triangle)s;
                t.triangle();
            }
            else{
                System.out.println("지원되지 않는 타입입니다.");
            }
        }
    }
}

public void testCasting() 메소드처럼 if-else 조건문을 이용하여 명시적으로 형 변환을 하고 하위 클래스에만 있는 메소드를 실행한다.

'Programming Language > 자바(JAVA)' 카테고리의 다른 글

Do it! 자바 프로그래밍 입문 / 10장 인터페이스  (0) 2023.01.16
Do it! 자바 프로그래밍 입문 / 9장 추상 클래스  (0) 2023.01.04
Do it! 자바 프로그래밍 입문 / 7장 배열과 ArrayList  (0) 2022.12.31
Do it 자바 프로그래밍 입문 연습문제 6장  (0) 2022.12.30
Do it! 자바 프로그래밍 입문 / 6장 클래스와 객체 2  (0) 2022.12.30
'Programming Language/자바(JAVA)' 카테고리의 다른 글
  • Do it! 자바 프로그래밍 입문 / 10장 인터페이스
  • Do it! 자바 프로그래밍 입문 / 9장 추상 클래스
  • Do it! 자바 프로그래밍 입문 / 7장 배열과 ArrayList
  • Do it 자바 프로그래밍 입문 연습문제 6장
토자맨
토자맨
  • 토자맨
    개발하는 토자맨
    토자맨
  • 전체
    오늘
    어제
    • 개발 공부
      • 코딩 테스트
        • 코드업 기초 100제
        • 백준
        • 99클럽
        • 자료구조
        • 알고리즘
      • Programming Language
        • 자바(JAVA)
      • Back-end
        • Spring
      • Front-end
        • html
        • css
      • DevOps
        • AWS
        • CI CD
        • Docker
        • 홈서버
        • Git
      • Computer Science
        • 자료구조
        • 알고리즘
        • 운영체제
        • OS,Network,DB,DesignPattern
      • 프로젝트
        • 웨이트 쇼핑몰
      • 공부 로드맵
        • 2학년 겨울방학
        • 3학년 2학기
        • 3학년 겨울방학
      • 일상
        • 기타 정보
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    99클럽 #코딩테스트 준비 #개발자 취업 #항해99 #til
    dfs #알고리즘
    백준 #dfs #알고리즘
    nvidia-docker #docker cuda #docker gpu #엔비디아 도커
    bfs #백준
    피보나치 수 #백준 #dp
    dfs #백준
    백준 #dp #동적계획법
    프로그래머스 #dfs
    이진탐색 #이분탐색 #알고리즘
    스프링 #spring #스프링 컨테이너 #스프링 컨텍스트
    싱글톤 패턴 #싱글톤 컨테이너 #싱글톤 레지스트리 #싱글톤 객체 상태 #무상태 #stateless #유지상태 #staleful
    nvidia container toolkit #
    백준 #bfs
    bfs #최단거리탐색 #프로그래머스
    백준 #이진탐색 #이분탐색
    백준 #dfs #11725번
    프로그래머스 #dp
    백준 #아기상어2 #bfs
    ec2 멈춤 #ec2 터짐 #ec2 ssh 연결 끊김 #ec2 끊김
    git filter-branch #commit 수정 #commit
    dp #백준 #동적계획법
    git filter-repo
    오블완
    solid #객체지향설계원칙
    티스토리챌린지
    이진탐색 #이분탐색 #백준
    bfs #프로그래머스
    스프링핵심원리 #김영한 #의존관계자동주입 #의존관계 자동 주입
    백준 #dfs
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
토자맨
Do it! 자바 프로그래밍 입문 / 8장 상속
상단으로

티스토리툴바