ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java]STEP1 - 11) 상속, 메소드 오버라이딩(Overriding), super(), final 클래스와 final 메소드, protected 접근 제한자
    개발 공부/Java 2020. 9. 24. 18:21

     

    본 게시글은 도서 "이것이 자바다" 동영상 강의를 듣고 기록하는 TIL(Today I Learned) 입니다.
    모든 저작권은 출판사 한빛미디어와 신용권님께 있음을 알립니다.👍

     

     

    이번에는 자바에서 가장 중요한 개념 중 하나인 상속에 대해서 공부해보았습니다.

    상속의 개념과 클래스를 상속하기 위한 문법, super() 를 통해 부모 생성자를 호출하기,

    메소드 오버라이딩의 개념, 활용 그리고 final 클래스와 final 메소드가 무엇인지

    마지막으로 상속과 관련있는 접근 제한자 protected란 무엇인지 알아보겠습니다.

     

    1. 상속(Inheritance)


    객체 지향 프로그래밍에서 상속이란 부모 클래스의 멤버를 자식 클래스에게 물려주는 것을 의미한다.

    이는 부모 클래스의 멤버를 물려받아, 자식 클래스에서의 코드의 중복을 줄여주고 효율적인 개발이 가능하도록 만든다.

     

    하지만 부모 클래스에서 모든 멤버를 물려받는 것은 아닌데,

    1. 부모 클래스에서 private 접근 제한을 갖는 필드와 메소드는 상속에서 제외된다.
    2. 부모 클래스와 자식 클래스가 다른 패키지에 존재하면 default 접근 제한을 갖는 필드와 메소드도 상속에서 제외된다.
    클래스를 상속하는 법은 다음과 같다.

    class 자식클래스 extends 부모클래스 {
        ...
    }

    주의할 점은 자바는 다중상속을 허용하지 않는다는 점이다.
    따라서 extends 다음에 부모클래스는 단 하나만 올 수 있다.

     

    부모 없는 자식이 없듯, 자바에서도 자식 객체를 생성하면 부모 객체가 먼저 생성되고 자식 객체가 그 다음에 생성된다.

    컴파일러는 따로 개발자가 명시하지 않으면, 자식 생성자의 맨 첫 줄에서 부모 생성자를 자동으로 호출한다.

    public class CellPhone extends Phone {
        
        public CellPhone () {
            super();
        }
    }

    super(); 는 부모의 기본 생성자를 호출하는 역할을 한다.
    위의 코드에 있는 super();는 CellPhone의 생성자에서 가장 첫 줄에서 호출되며,
    Phone의 기본 생성자를 불러왔다.

    super();는 개발자가 따로 선언하지 않아도, 자동으로 컴파일러가 선언하게 되며
    만약 부모 생성자에 매개변수가 존재한다면, 이때에는 개발자가 아래처럼 반드시 따로 선언을 해야한다.

    public class CellPhone extends Phone {

        public CellPhone (String name) {
            super(name);
        }
    }

     


     

    2. 메소드 오버라이딩(Overriding)


    부모 클래스의 어떤 메소드는 자식 클래스가 사용하기에 적합하지 않을 수 있다.

    이 경우에는 상속된 일부 메소드는 자식 클래스에서 다시 수정해서 사용해야 한다.

     

    메소드 오버라이딩(Overriding) 기능은 자식 클래스에서 부모 클래스에 있는 메소드와 동일한 메소드를 재정의 하는 것을 말한다.

    메소드가 오버라이딩 되었다면, 자식 객체에서 해당 메소드를 호출 했을 때 원래 부모 객체의 메소드가 아니라 재정의 된 자식 객체의 메소드가 호출된다.

    //부모 클래스
    class Parent {
        void method1() { }
        void method2() { }
    }

    //자식 클래스
    class Child {
        void method2() { }  // 메소드 오버라이딩(재정의)
        void method3() { }
    }

    // Main
    class ChildExample {
        public static void main(String[] args) {
            Child child = new Child();
            child.method1();
            child.method2();
            child.method3();
        }
    }

    위의 경우, Child라는 자식 클래스에서 Parent라는 부모 클래스에 이미 존재하는 method2를 재정의 하였다.
    그렇게 되면, main 함수에서 실행했을 때 child.method2(); 에 의해서 실행되는 메소드는
    Parent 부모 클래스의 method2() 가 아니라, Child 자식 클래스의 method2();이다.

    이것을 바로 메소드 오버라이딩이라고 한다.

     

    메소드 오버라이딩은 다음과 같은 규칙이 있다.

    • 부모의 메소드와 동일한 리턴타입, 메소드이름, 매개 변수 리스트를 가져야 한다.
    • 접근 제한을 더 강하게 오버라이딩 할 수 없다. (ex. public에서 default나 private로 수정 불가)
    • 새로운 예외를 throws할 수 없다.

     

    @Override 어노테이션을 이용하면, 재정의한 메소드가 정확히 오버라이딩이 되었는지 컴파일러가 확인해 준다.

    따라서 자식 클래스에 재정의하는 메소드 이름 위에 @Override를 붙여 개발자의 실수를 줄일 수 있다.

     

    또한 super를 이용하면 재정의된 메소드가 아니라, 원래의 부모 클래스의 메소드를 호출 할 수 있다.

    //부모 클래스
    class Parent {
        void method1() { }
        void method2() { }
    }

    //자식 클래스
    class Child {
        void method2() { }  // 메소드 오버라이딩(재정의)
        void method3() { 
            method2();
            super.method2();
        }
    }

    Child 자식 클래스의 method3() 내부에 쓰여진 코드를 살펴보자.
    일단 method2()는 Child 클래스에서 메소드 오버라이딩으로 재정의 되었다.
    그렇기 때문에 method2(); 부분은 오버라이딩 된 method2()가 실행이 될 것이다.
    하지만 바로 다음 줄에 있는 super.method2(); 는 부모 메소드를 호출하는 부분이다.
    따라서 Parent 부모 클래스의 method2()가 실행이 될 것이다.

    이처럼 super 키워드를 붙이면 오버라이딩 된 메소드가 아니라 원래 부모 클래스에 있는 메소드가 호출된다.

     


     

    3. final 클래스와 final 메소드


    final 키워드는 클래스, 필드, 메소드 선언 시에 사용할 수 있다.

     

    final 필드에 대해서는 앞서 [Java]STEP1 - 8번 게시물에서 알아보았다.

     

    [Java]STEP1 - 8) 인스턴스 멤버, 정적 멤버, this, static, 싱글톤, final과 상수(static final)

    본 게시글은 도서 "이것이 자바다" 동영상 강의를 듣고 기록하는 TIL(Today I Learned) 입니다. 모든 저작권은 출판사 한빛미디어와 신용권님께 있음을 알립니다.👍 이번 게시물에서는 인스턴스 멤버

    kyleyj.tistory.com

     

    이번에는 클래스와 메소드에 final 키워드가 지정되면 어떤일이 일어날지 알아본다.

     

    3-1) 상속할 수 없는 final 클래스

    클래스를 선언할 때 final 키워드를 class 앞에 붙이게 되면 이 클래스는 최종적인 클래스이므로 상속할 수 없는 클래스가 된다. 즉 final 클래스는 부모 클래스가 될 수 없다.

    public final class Phone {
        ....
    }

    위와 같이 final 클래스가 선언 될 수 있다.
    final 클래스는 상속이 불가 하기 때문에 아래와 같은 코드는 잘못된 것이다.

    public class NewPhone extends Phone {
        ....
    }

    final 클래스인 Phone을 상속 할 수 없다.

     

    final 클래스의 대표적인 예로는 String 클래스가 있다.

     

     

     

    3-2) 오버라이딩 할 수 없는 final 메소드

    메소드를 선언할 때 final 키워드를 붙이게 되면 이 메소드는 최종적인 메소드이므로 오버라이딩(재정의)할 수 없는 메소드가 된다. 즉 final 메소드는 자식 클래스에서 재정의 할 수 없다.

    public class Car {
        public final void stop() {
            System.out.println("차를 멈춥니다.");
        }
    }

    위와 같이 final 메소드가 선언 될 수 있다.
    final 메소드는 오버라이딩이 불가 하기 때문에 아래와 같은 코드는 잘못된 것이다.

    public class NewCar extends Car {
        @Override
        public void stop() {
            System.out.println("차를 당장 멈춥니다.");
        }
    }

    final 메소드인 stop() 을 오버라이딩(재정의) 할 수 없다.

     


     

    4. protected 접근 제한자


    접근 제한자는 public, protected, default, private 총 네 종류가 있다.

    이 접근 제한자들에 대해서는 앞선 게시물에서 알아보았다.

     

    [Java]STEP1 - 9) 패키지, import, 접근 제한자(public, protected, default, private), Getter와 Setter

    본 게시글은 도서 "이것이 자바다" 동영상 강의를 듣고 기록하는 TIL(Today I Learned) 입니다. 모든 저작권은 출판사 한빛미디어와 신용권님께 있음을 알립니다.👍 이번 게시물에서는 패키지의 개념

    kyleyj.tistory.com

     

    이 중에서 특히나 protected 접근 제한자는 상속의 개념과 관련있기 때문에 이 장에서 다시 한번 설명된다.

     

    protected는 public과 default 접근 제한의 중간쯤 해당한다.

    같은 패키지에서는 default와 같이 접근 제한이 없으나, 다른 패키지에서는 자식 클래스에게만 접근을 허용한다.

    package package1;

    public class A {
        protected String field;

        protected A() {
        }

        protected void method() {
        }
    }

    위와 같이 A라는 클래스가 package1이라는 패키지에 선언이 되어있다고 가정한다.
    A 클래스 안에는 필드, 생성자, 메소드가 현재 protected 접근 제한자를 통해 선언되어 있다.

    이렇게 되면 같은 패키지에서는 접근 제한이 없으나, 다른 패키지에서는 A 클래스의 자식 클래스에게만 접근을 허용한다.

    예를 들면,
    동일 패키지인 package1에 있는 B라는 클래스
    다른 패키지인 package2에 있는 C라는 클래스
    다른 패키지인 package2에 있지만 A 클래스를 상속하는 D라는 클래스
    이렇게 세 클래스가 있다고 해보자.

    B클래스는 동일 패키지에 있으므로 A 클래스의 어떠한 필드, 생성자, 메소드에도 접근 가능하다.
    C클래스는 다른 패키지에 있고, A 클래스를 상속하지 않기 때문에 어떠한 필드, 생성자, 메소드에도 접근이 불가능하다.
    D클래스는 다른 패키지에 있지만, A 클래스를 상속하기 때문에 어떠한 필드, 생성자, 메소드에도 접근 가능하다.

     

     

    본 게시글은 여기서 마치겠습니다.

    읽어주셔서 감사하고, 혹시나 틀린 부분이나 보완해야할 부분이 있다면 댓글에 남겨주세요~!

    댓글

Designed by Tistory.