ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Study] 자바 6주차 과제
    JAVA 2021. 1. 15. 16:11
    반응형

    자바 6주차 과제입니다.

     

     


     

    자바 상속의 특징

     

    상속이란?

    상속이란 기존의 클래스를 재사용해 새로운 클래스를 만드는 것을 뜻합니다.

    적은 양의 코드로 새로운 클래스를 만들 수 있으며 코드를 한 번에 관리할 수 있습니다.

    상속을 해주는 클래스는 상위 클래스(Super class), 상속을 받는 클래스를 하위 클래스(Sub class)라고 합니다.

    상위 클래스는 보통 부모 클래스(Parent class), 하위 클래스는 자식 클래스(Child class)라고 부릅니다.

     

    • 상위 클래스(Super Class) - 부모 클래스(Parent Class), 기반 클래스(Base Class)
    • 하위 클래스(Sub Class) - 자식 클래스(Child Class)

     

     

    사용 방법

     

    확장하다는 의미인 extends 키워드를 사용하여 구현할 수 있습니다.

     

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

     

     

    자바 상속의 특징

     

    • 자바에서는 다중 상속이 불가능 합니다. (단일 상속만 가능합니다)
    • 자바의 계층 구조 최상위에는 Object 클래스가 존재합니다.
    • 자바에서는 상속의 횟수에 제한을 두지 않습니다.
    • 부모 클래스의 생성자와 초기화 블럭은 상속되지 않습니다.
    class Parent {
        //부모 클래스의 변수와 메소드
        // ...
    }
    
    class Child extends Parent {
        //자식 클래스에서 부모 클래스의 변수와 메소드 사용 가능
        //단, 전부 사용 가능한 것은 아님. 접근 제어자에 따라 다르다.
        // ...
    }
    

     

     

     

     

    super 키워드

     

    class Parent {
        int age;
        Parent() {
            age = 50;
        }
    }
    
    class Child extends Parent {
        int age;
        Child() {
            super();
            this.age = 10;
            System.out.println(this.age);
            System.out.println(super.age);
        }
    }
    
    public class Inheritance {
        public static void main(String[] args) {
            Child child = new Child();
            //출력
            //10
            //50
        }
    }

     

     

    super 참조 변수

     

    super 참조 변수는 부모 클래스로부터 상속받은 필드나 메소드를 자식 클래스에서 참조하는데 사용하는 것입니다.

    인스턴스 변수의 이름과 지역 변수의 이름이 같을 경우 인스턴스 변수 앞에 this 키워드를 사용하여 구별할 수 있었던 것과 마찬가지로 부모 클래스의 멤버와 자식 클래스의 멤버 이름이 같을 경우 super 키워드를 사용하여 구별할 수 있습니다.

    또한 this와 마찬가지로 super 참조 변수를 사용할 수 있는 대상은 인스턴스 메소드뿐이며, 클래스 메소드에서는 사용할 수 없습니다.

     

     

    super() 메소드

     

    this() 메소드가 같은 클래스의 다른 생성자를 호출할 때 사용된다면, super() 메소드는 부모 클래스의 생성자를 호출할 때 사용됩니다.

    자식 클래스의 인스턴스를 생성하면 부모 클래스의 모든 멤버까지도 포함되어 있기 때문에, 부모 클래스의 멤버를 초기화하기 위해서 자식 클래스의 생성자에서 부모 클래스의 생성자까지 호출해야만 합니다.

    따라서 자바 컴파일러는 부모 클래스의 생성자를 명시적으로 호출하지 않는 모든 자식 클래스의 생성자 첫 줄에 자동으로 super()를 추가하여, 부모 클래스의 멤버를 초기화할 수 있도록 해줍니다.

     

    메소드 오버라이딩

     

    class Parent {
        //부모 클래스의 변수와 메소드
        // ...
        int age;
        Parent() {
            age = 50;
        }
    
        Parent method() {
            return null;
        }
    
        void display() {
            System.out.println("부모 클래스 display() 메소드입니다.");
        }
    }
    
    class Child extends Parent {
        //자식 클래스에서 부모 클래스의 변수와 메소드 사용 가능
        //단, 전부 사용 가능한 것은 아님. 접근 제어자에 따라 다르다.
        // ...
        int age;
        Child() {
            super();
            this.age = 10;
            System.out.println(this.age);
            System.out.println(super.age);
        }
    
        @Override
        Child method() { //Child 타입은 Parent의 자식 클래스이므로 리턴 타입 변경 가능(다형성)
            return null;
        }
    
        @Override
        void display() {
            System.out.println("자식 클래스의 display() 메소드입니다.");
        }
    }

     

    메소드 오버라이딩(overriding)이란 상속 관계에 있는 부모 클래스에서 이미 정의된 메소드를 자식 클래스에서 같은 시그니쳐를 갖는 메소드로 다시 정의하는 것이라고 할 수 있습니다.

    자바에서 자식 클래스는 부모 클래스의 private 멤버를 제외한 모든 메소드를 상속받는데 이를 그대로 사용해도 되고, 필요한 동작을 위해 재정의하여 사용할 수도 있습니다.

    즉, 메소드 오버라이딩이란 상속받은 부모 클래스의 메소드를 재정의하여 사용하는 것을 의미합니다.

     

     

    오버라이딩의 조건은 다음과 같습니다.

    1. 오버라이딩이란 메소드의 동작만을 재정의하는 것이므로, 메소드의 선언부는 기존 메소드와 완전히 같아야합니다. 하지만 메소드의 반환 타입은 부모 클래스의 반환 타입으로 타입 변환할 수 있는 타입이라면 변경할 수 있습니다.
    2. 부모 클래스의 메소드보다 접근 제어자를 더 좁은 범위로 변경할 수 없습니다.
    3. 부모 클래스의 메소드보다 더 큰 범위의 예외를 선언할 수 없습니다.

     

     

     

    다이나믹 메소드 디스패치 (Dynamic Method Dispatch)

     

    메소드 디스패치(Method Dispatch)

     

    메소드 디스패치란 어떤 메소드를 호출할 지 실제로 실행시키는 과정을 말합니다.

    메소드 디스패치에는 정적 메소드 디스패치(Static Method Dispatch), 동적 메소드 디스패치(Dynamic Method Dispatch), 더블 디스패치(Double Dispatch) 세 가지가 존재합니다.

     

     

     

    정적 메소드 디스패치(Static Method Dispatch)

     

    class Parent {
        void display() {
            System.out.println("부모 클래스 display() 메소드입니다.");
        }
    }
    
    class Child extends Parent {  
        @Override
        void display() {
            System.out.println("자식 클래스의 display() 메소드입니다.");
        }
    }
    
    public class Inheritance {
        public static void main(String[] args) {
            Child child = new Child();
            child.display(); //자식 클래스의 display() 메소드입니다. 출력
        }
    }

     

    메인에서 display() 메소드를 호출했을 때 개발자는 클래스 Child의 오버라이딩 된 메소드가 호출될 것을 알고 있습니다. 개발자가 알고 있는 것과 같이 컴파일 시점에서 컴파일러가 특정 메소드를 호출할 것이라는 것을 명확하게 알고있는 경우를 정적 메소드 디스패치라고 합니다. 

     

     

    동적 메소드 디스패치(Dynamic Method Dispatch)

     

    interface C {
        void print();
    }
    
    class A implements C {
        public void print() {
            System.out.println("A 입니다.");
        }
    }
    
    class B implements C {
        public void print() {
            System.out.println("B 입니다.");
        }
    }
    
    public class Dispatch {
        public static void main(String[] args) {
            C c1 = new A();
            C c2 = new B();
            c1.print();
            c2.print();
        }
    }
    

     

    위 예제에서 C 인터페이스를 A와 B 클래스가 상속하고 있습니다.

    다형성을 이용해 메인에서 A와 B 둘다 C타입으로 선언하고 각각 클래스 내에서 구현한 print() 메소드를 실행시키고 있습니다. 개발자는 이 c1, c2라는 인스턴스의 print() 메소드가 어디에서 구현한 메소드인지 유추가 가능하지만 컴파일러는 이에 대해 알 수 있는 방법이 없습니다. 즉, 컴파일러는 어떤 함수가 실행될 지 전혀 모르고 런타임 시점이 되어야 어떤 메소드를 가져와야할 지 알게 될 것입니다. 

    이처럼 컴파일러가 어떤 메소드를 호출해야되는지 모르는 것을 동적 메소드 디스패치라고 합니다.

     

     

    더블 디스패치(Double Dispatch)

     

    package inheritance;
    
    import java.util.Arrays;
    import java.util.List;
    
    interface Post {
        void postOn(SNS sns);
    }
    
    class Text implements Post {
        public void postOn(SNS sns) {
            sns.post(this);
        }
    }
    
    class Picture implements Post {
        public void postOn(SNS sns) {
            sns.post(this);
        }
    }
    
    interface SNS {
        void post(Text text);
        void post(Picture picture);
    }
    
    class Facebook implements SNS {
        public void post(Text text) {
            //text -> facebook
        }
    
        public void post(Picture picture) {
            //picture -> facebook
        }
    }
    
    class Twitter implements SNS {
        public void post(Text text) {
            //text -> facebook
        }
    
        public void post(Picture picture) {
            //picture -> facebook
        }
    }
    
    public class Double_Dispatch {
        public static void main(String[] args) {
            List<Post> posts = Arrays.asList(new Text(), new Picture());
            List<SNS> sns = Arrays.asList(new Facebook(), new Twitter());
    
            posts.forEach(post -> sns.forEach(s -> post.postOn(s)));
        }
    }
    

     

    더블 디스패치는 말그대로 다이나믹 메소드 디스패치를 두 번 하는 것을 의미합니다.

    위 예제에서

    1. Post에서 어떤 구현 클래스의 postOn() 메소드를 호출할 지
    2. postOn() 메소드에서 SNS의 어떤 구현 클래스의 post() 메소드를 호출할 지

    이렇게 두 번의 다이나믹 메소드 디스패치가 이루어집니다. 이를 통해 구현 클래스를 생성하는 것에 자유로워지게 됩니다. 만약 다른 sns를 추가하고 싶으면 facebook, twitter 클래스와 같은 형식으로 이름만 바꿔 추가해주면 됩니다.

     

     

     

     

    추상 클래스

     

    추상 메소드(abstract method)

     

    추상 메소드란 자식 클래스에서 반드시 오버라이딩해야만 사용할 수 있는 메소드를 의미합니다.

    자바에서 추상 메소드를 선언하여 사용하는 목적은 추상 메소드가 포함된 클래스를 상속받는 자식 클래스가 반드시 추상 메소드를 구현하도록 하기 위함입니다.

     

    이러한 추상 메소드는 선언부만이 존재하며, 구현부는 작성되어 있지 않습니다.

    바로 이 작성되어 있지 않는 구현부를 자식 클래스에서 오버라이딩하여 사용하는 것입니다.

     

    abstract 반환타입 메소드이름();

     

     

     

    추상 클래스(abstract class)

     

    자바에서 하나 이상의 추상 메소드를 포함하는 클래스를 가리켜 추상 클래스라고 합니다.

    이러한 추상 클래스는 객체 지향 프로그래밍에서 중요한 특징인 다형성을 가지는 메소드의 집합을 정의할 수 있도록 해줍니다. 

    즉, 반드시 사용되어야 하는 메소드를 추상 클래스에 추상 메소드로 선언해 놓으면, 이 클래스를 상속받는 모든 클래스에서는 이 추상 메소드를 반드시 재정의해야 합니다.

     

    abstract class 클래스 이름 {
    	...
        abstract 반환타입 메소드이름();
        ...
    }

     

    이러한 추상 클래스는 동작이 정의되어 있지 않은 추상 메소드를 포함하고 있으므로, 인스턴스를 생성할 수 없습니다.

    추상 클래스는 먼저 상속을 통해 자식 클래스를 만들고, 만든 자식 클래스에서 추상 클래스의 모든 추상 메소드를 오버라이딩하고 나서야 비로소 자식 클래스의 인스턴스를 생성할 수 있게 됩니다.

     

     

     

     

    final 키워드

     

    final 키워드는 엔티티를 한 번만 할당하겠다는 의미로 자바에서는 총 세 가지 의미로 사용됩니다.

     

    • final 변수

      변수에 final을 사용하게 되면 상수가 됩니다. 생성자나 대입연산자를 통해 한 번만 초기화 가능한 변수입니다.
    • final 메소드

      final 메소드는 오버라이드하거나 숨길 수 없음을 의미합니다.

    • final 클래스

      해당 클래스를 상속할 수 없음을 의미합니다. 상속할 수 없기 때문에 계층에서 마지막 클래스라는 것을 의미합니다.

     

     

     

     

    Object 클래스

     

     

    Object 클래스는 모든 자바 클래스의 최고 조상 클래스가 됩니다.

    따라서 자바의 모든 클래스는 Object 클래스의 모든 메소드를 바로 사용할 수 있습니다.

    이러한 Object 클래스는 필드를 가지지 않으며, 총 11개의 메소드만으로 구성되어 있습니다.

     

    출처 : http://www.tcpschool.com/java/java_api_object

     

     

     

    References

     

    - www.tcpschool.com/java/java_inheritance_overriding

    - www.notion.so/e5c33507880b4d098f83a2c4f8f02c04

    - blog.naver.com/swoh1227/222181505425

    - leemoono.tistory.com/20

    - bbigbros.tistory.com/entry/%EC%9E%90%EB%B0%94JAVA-%EC%83%81%EC%86%8DInheritance%EC%9D%98-%EA%B0%9C%EB%85%90

    - blog.naver.com/sejonghumble/222183439699

    - www.tcpschool.com/java/java_polymorphism_abstract

    - www.tcpschool.com/java/java_api_object

    728x90

    'JAVA' 카테고리의 다른 글

    [Study] 자바 8주차 과제  (0) 2021.01.24
    [Study] 자바 7주차 과제  (0) 2021.01.18
    [Study] 자바 5주차 과제  (0) 2021.01.10
    [Study] 자바 4주차 과제  (1) 2020.12.08
    [Study] 자바 3주차 과제  (0) 2020.11.28

    댓글

Designed by Tistory.