클래스

객체를 생성하면 참조값 주소가 반환된다.

 

Parent parent = new Parent();

new Parent() : 객체 생성, 주소값 반환  -> 메모리에 실제 객체 생성  

parent : 반환되는 주소값 저장  -> 실제 객체에 접근 가능 

 

인스턴스 : 특정 클래스로부터 생성된 객체  

 

클래스에는 public 과 default 만 허용된다.(생략 시 default 사용) 

하나의 자바 파일에 public 클래스는 하나만 등장 가능하다. 

 

 

다형성

한 객체가 여러 타입의 객체로 취급될 수 있는 것..

 

메서드 오버라이딩과 변수

public class Parent {

    String type = "parent";

    void method1() {
        System.out.println("Parent -> method1()");
    }
    void method2() {
        System.out.println("Parent -> method2()");
    }
}

 

class Child extends Parent {

    String type = "child";

    void method1() {
        System.out.println("Child -> method1()");
    }
    void method2() {
        System.out.println("Child -> method2()");
    }
    void childMethod() {
        System.out.println("Child -> childMethod()");
    }
}

 

public class Main {

    public static void main(String[] args) {

        Parent person = new Child();
        
        System.out.println("type = " + person.type);
        
        person.method1();
    }
}

 

결과

type = parent

Child -> method1()

 

이유

Parent person = new Child();

System.out.println(person) 으로 person 의 주소값을 확인해보니 Child@682a0b20 가 나왔다. 

Child 와 Parent 생성되었고 person은 Parent 가리키고 있음

 

person.type 은 Parent 타입에 있는 type 을 읽음

 

person.method1();

person 이 Parent 타입이지만 하위 타입 Child 의 method1() 이 Parent 의 method1() 을 오버라이딩 하고있음

오버라이딩 된 메서드가 우선권을 가지기 때문에 오버라이딩 된 메서드가 호출됨

=> Child -> method1() 출력됨

 

 

this

아까 코드에서 일부분만 변경해보자

 

public class Parent {

    String type = "parent";

    void method1() {
        System.out.println("this = " + this);  // 변경된 부분
        this.method2();  // 변경된 부분
        System.out.println("Parent -> method1()");
    }
    void method2() {
        System.out.println("Parent -> method2()");
    }
}

 

class Child extends Parent {

    String type = "child";
    
    /**
    *  method1() 삭제
    */

    void method2() {
        System.out.println("Child -> method2()");
    }
    void childMethod() {
        System.out.println("Child -> childMethod()");
    }
}

 

public class Main {



    public static void main(String[] args) {

        Parent person = new Child();
        System.out.println("type = " + person.type);
        System.out.println("person = " + person);
        person.method1();
    }
}

 

결과

type = parent

person = Child@682a0b20

this = Child@682a0b20

Child -> method2()

Parent -> method1()

 

type = parent 는 당연하니 넘어가고

Child -> method2() 에서 의문이 생겼다.

 

Parent 클래스 안에 있는 method1() 에서 호출한 this.method2() 가 왜 Child 클래스로 넘어가는 걸까?

 

결론은 또 오버라이딩에 있다. 

this 로 불러온건 Parent 타입이지만 하위 타입 Child 의 method2() 이 Parent 의 method2() 를 오버라이딩 하고있음

오버라이딩 된 메서드가 우선권을 가지기 때문에 오버라이딩 된 메서드가 호출된다.

 

 

오버라이딩이 아닌 자식 클래스의 메서드

class Child extends Parent {

    String type = "child";
    
    /**
    *  method1() 삭제
    */

    void method2() {
        System.out.println("Child -> method2()");
    }
    void childMethod() {
        System.out.println("Child -> childMethod()");
    }
}

 

아까 위에 작성한 Child 클래스이다. 아래쪽에 보면 Child 클래스만 가지고 있는 childMethod() 가 보인다.

 

Parent person = new Child() ;

person.childMethod();

 

이렇게 코드를 작성하면 어떻게 될까?

 

컴파일 에러가 발생한다.

 

person 은 어디까지나 Parent 타입이다. 따라서 자식 클래스가 가지고 있는 '오버라이딩 되지 않은 메서드' 를 호출할 수 없다.

 

만약 정말 호출하고 싶다면 

 

((Child)person).childMethod(); 

 

를 이용하여 person 을 다운캐스팅 해주어야 한다. 

역시나 ((Child)person) 의 주소값과 person 의 주소값은 동일하다.

 

이후에 클래스가 캐스팅을 어떻게 구분하는지 탐구하여 포스팅 할 예정이다.