2 분 소요

1. 개요

분명 공부했지만 누가 불시에 물어보면 맨날 헷갈리는 상속에 관한 내용을 한번 정리해보도록 하자 🤣

2. 접근제어자

키워드 사용 범위 클래스에 사용할 시
public 전 범위 - 클래스명과 소스파일명 일치
- 한 소스파일 내에 하나만 존재 가능
default (생략) 같은 패키지 내  
private 해당 클래스 내부 InnerClass 를 정의할 시에만 사용
protected 해당 클래스 및 상속클래스 내부 InnerClass 를 정의할 시에만 사용

3. final 키워드

필드

선언 후 초기화가 이루어지면 절대로 값을 변경할 수 없는 상수가 된다.

메소드

오버라이딩이 불가능해진다.

클래스

해당 클래스를 상속받는 서브 클래스를 정의할 수 없다.

4. static 키워드

필드

특정 객체에 static 필드가 존재하면 다른 참조값을 가지는 객체가 아무리 많아도 같은 값을 공유한다.

메소드

객체의 인스턴스와 무관하게 어디서든 호출이 가능하므로 non-static 필드나 메소드를 호출할 수 없다.

클래스

static 키워드는 원래 클래스에는 붙일 수 없으나, 예외적으로 중첩 클래스(inner class) 를 선언할 때에 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class Scratch {

    public static void main(String[] args) throws IOException {

        // Static 중첩 클래스는 부모 클래스 인스턴스가 없어도 생성할 수 있음
        OuterClass.NestedStaticClass nsc = new OuterClass.NestedStaticClass();
        nsc.printStaticMsg();

        // 일반 중첩 클래스는 부모 클래스 인스턴스가 선언되어야지만 생성할 수 있음
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass inner = outer.new InnerClass();
        inner.printMsg();

        // 아래와 같은 형태로도 선언 가능
        OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();

        innerObject.printStaticMsg();

    }
}

class OuterClass {

    private static String msg = "정적 메시지";
    private String msg2 = "일반 메시지";

    public static class NestedStaticClass {
        public void printStaticMsg() {
            System.out.println("[Static 중첩 클래스에서 호출 됨] : " + msg);
        }
// ERROR -> Static 중첩 클래스에서는 Non-Static 필드를 호출할 수 없음
//      public void printMsg() {
//          System.out.println("[Static 중첩 클래스에서 호출 됨] : " + msg2);
//      }
    }

    public class InnerClass {
        public void printStaticMsg() {
            System.out.println("[INNER 클래스에서 호출 됨]" + msg);
        }
        public void printMsg() {
            System.out.println("[INNER 클래스에서 호출 됨]" + msg2);
        }
    }
}

실행결과

5. 캡슐화

클래스 내의 필드를 private 접근제어자로 선언하여 외부에서 쉽게 제어하지 못하도록 하고, 명시적인 public 메소드를 통해 값을 제어한다.

6. 오버로딩과 오버라이딩

오버로딩

메소드 재정의 - 이름은 동일하나 매개변수가 다른 메소드를 정의하는 것

오버라이딩

  • 접근제어자는 범위가 넓어지는 쪽으로 재설정 할 수 있다.
  • 메소드 상속 재정의 - 부모의 메소드를 상속받으며 반환형, 매개변수 목록, 메소드 이름은 그대로 두고 몸체의 정의를 새로 하는 것

메소드의 이름과 매개변수를 묶어 메소드의 서명(signature) 이라고 한다. 한 클래스 내에 서명이 동일한 두개 이상의 메소드가 존재할 수 없다.

7. 상속과 생성자

  • 상속 받은 클래스를 컴파일 할 때 부모 클래스의 기본 생성자를 호출한다.
  • 기본 생성자가 정의되어 있지 않을 시 컴파일러가 생성한다.
  • 결국 모든 객체는 Object 객체를 상속 받으므로 Object 의 기본 생성자를 호출한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class ParentClass { // extends Object

    public ParentClass() {
        // super(); -> 컴파일 시점에 Object 의 기본 생성자를 호출 한다.;
        System.out.println("[PARENT] 인자없는 부모 클래스 호출입니다.");
    }

    public ParentClass(int a) {
        System.out.println("[PARENT, PARAM] 인자있는 부모 클래스 호출입니다.");
    }
}

class ChildClass extends ParentClass {

    public ChildClass() {
        // super(); -> 컴파일 시점에 부모 클래스의 기본 생성자를 호출한다.
        System.out.println("[CHILD] 인자없는 자식 클래스 호출입니다.");
    }

    public ChildClass(int a) {
        System.out.println("[CHILD, PARAM] 인자있는 자식 클래스 호출입니다.");
    }
}

class InheritanceConstructor {

    public static void main(String[] args) {
        ChildClass childClassA = new ChildClass();
        ChildClass childClassB = new ChildClass(10);
    }

}

실행 결과

태그: ,

카테고리:

업데이트: