[Java] 상속 상황에서 생성자 사용시 주의점

hwhyeons·2023년 1월 9일
0

자바

목록 보기
1/1

부모 클래스와 자식클래스가 상속 관계일 때,
부모의 생성자에서 메소드를 호출하게 될 때 큰 문제가 발생할 수 있다.

class Parent {
    public Parent() {
        System.out.println("부모 생성자");
        f();
    }

    public void f() {
        System.out.println("부모의 메서드");
    }
}

class Child extends Parent {
    @Override
    public void f() {
        System.out.println("자식의 오버라이딩 메서드");
    }

    public Child() {
        System.out.println("자식의 생성자");
    }
}


public class Test {
    public static void main(String[] args) {
        Child c = new Child();
    }
}

위와 같은 코드에서 메인 메소드를 실행하게 되면

이와 같이 출력되는데, 자식의 생성자가 호출되기도 전에
자식에 있는 메소드가 먼저 호출되는 것을 볼 수 있다.

특히

    public Parent() {
        System.out.println("부모 생성자");
        f();
    }

이 부분에서 Parent의 생성자의 f()는 코드만 봤을 때는
그 어느 부분도 자식의 f()를 호출하라고 한 적이 없지만,

    @Override
    public void f() {
        System.out.println("자식의 오버라이딩 메서드");
    }

이렇게 자식 클래스에 f()가 오버라이딩 되었기 때문에
Child의 생성자가 호출되기 전에 부모의 f()를 부르는 상황에서
자식의 f()가 호출되었다.

이렇게 되면 자식 생성자에서 어떤 값을 초기화 해주기 전에
f()가 해당 멤버를 사용하게 되면 큰 문제가 발생할 수 있다.

class Parent {
    String name;

    public Parent() {
        this.name = "철수";
        f();
    }

    public void f() {
        System.out.println("부모 클래스 이름 : "+name);
    }
}

class Child extends Parent {
    String name;
    @Override
    public void f() {
        System.out.println("자식 클래스 이름 : "+name);
    }

    public Child() {
        this.name = "홍길동";
    }
}

이 코드에서 아까와 같이 Child c = new Chlid()로 인스턴스를 만들게 되면

null이다.
생성자가 name멤버에 값을 넣어주기 전에 자식의 f()를 먼저호출 했기 때문에
이런 일이 발생하게 된다.

이 코드는 단순히 print하는 문장이므로 null로 출력이 되지만,
저 멤버를 이용해 다른 작업을 하는 경우 NullPointer로 런타임 오류가
발생하거나, 아예 잘못 수정해서 코드가 꼬여버리는 일이 발생할 수 있게 된다.

따라서 이런 경우, 상속 될 수 있는 부모 클래스의 경우 생성자에서
자신의 메소드를 호출하는 것을 지양하거나, 또는 아예 자식클래스에서
오버라이딩을 사용하지 못하게 부모 클래스의 해당 메소드를 private으로
바꿔버리는 방법이 있다.

0개의 댓글

관련 채용 정보