강의

멘토링

로드맵

인프런 커뮤니티 질문&답변

양성빈(Robert)님의 프로필 이미지
양성빈(Robert)

작성한 질문수

자바 개발자를 위한 코틀린 입문(Java to Kotlin Starter Guide)

10강. 코틀린에서 상속을 다루는 방법

코틀린에서 상속 시, 주의점에 대한 질문

작성

·

32

1

태현님, 안녕하세요. 뭔가 하나 더 궁금해져서 질문을 드리게 되었습니다!

아래의 두 클래스가 있다고 가정해보겠습니다.

package me.sungbin.lec10

open class Base(
    open number: String = "100",
) {
    init {
        println("Base Class")
        println(number)
    }
}
package me.sungbin.lec10

class Derived(
    override val number: String,
) : Base() {
    init {
        println("Derived Class")
    }
}

그리고 실제로 아래와 같이 Derived 클래스의 생성자를 호출하면 number값으로는 null이 출력됩니다.

 

여기서 궁금한 것은 number는 non-nullable한 타입인데 null이 왜 출력이 될까? 라는 궁금증이 생겼는데요..

그래서 GPT한테 물어보니 아래와 같은 답변을 얻을 수 있었습니다.

레퍼런스 타입(예: String) → JVM 기본값 null
이 출력됩니다. (Kotlin의 Non-null 보장도 생성 중(super 생성자 실행 중)에는 예외적으로 깨질 수 있습니다.)

이렇게 들으니 뭔가 이해가 된 듯 보이는데 이게 GPT 피셜이다보니 태현님의 의견이 듣고 싶어져서 질문을 남깁니다!

답변 3

1

최태현님의 프로필 이미지
최태현
지식공유자

안녕하세요! 보내주신 블로그 글까지 확인 완료했습니다.

상위 클래스와 하위 클래스의 초기화 시점에 따라 기본값이 들어갈 수 있다는 것 까지는 확인하신 것 같아요!

분명 선언된 것은 non-nullable 타입인데 어떻게 null이 나오는거야?

에 대해서만 더 말씀드리면. 코틀린은 결국 컴파일을 통해 .class 파일로 변환되어 JVM에서 실행됩니다!! 그리고 코틀린의 변수가 non-nullable인지, nullable인지 구분할 수 있는 것은 코틀린 언어 단에서 지원하는 것이지 .class 레벨에서는 관련한 스펙이 없습니다.

따라서 코틀린의 String? 을 디컴파일 하건 String 을 디컴파일 하건 코드가 실행될 때는 java의 String 처럼 동작하게 되고, 아직 초기화 되지 않은 경우는 reference type의 기본값인 null이 들어가게 되는 것입니다.

 

마찬가지로 이런 원리 때문에 "플랫폼 타입" 이라는 개념이 존재하게 됩니다! 코틀린의 코드가 자바의 코드를 부르는 경우, 결국 .class 코드가 .class 코드를 부르는 것이기에 코틀린 쪽에서 non-nullable 선언을 하더라도 자바 쪽 .class 에서 null이 넘어오면 코드가 깨질 수 있게 되는 것이죠.

답변이 도움이 되었으면 좋겠습니다! 감사합니다. 🙇

태현님 휴일에도 답변을 달아주셔서 감사드립니다 🙏

확실히 제가 경험한 실무에서는 이런 이슈가 없었는데 다시한번 공부하는 계기가 된 것 같습니다! 감사합니다!

0

제가 연구한 결과를 인프런 블로그로 남겨보았는데, 태현님이 혹시 다른 의견이 있으시거나, 제 내용 중 틀린 내용이 존재한다면 말씀 부탁드리겠습니다!

https://inf.run/PPp5k

0

안녕하세요, 인프런 AI 인턴입니다. 양성빈(Robert)님.

코틀린에서 상속을 사용하면서 발생하는 이슈에 대해 아주 좋은 질문을 주셨습니다. 말씀하신 상황은 클래스 생성자 호출 시점을 이해하는 데 매우 중요한 예시입니다.

코틀린에서는 클래스의 프로퍼티가 open으로 선언되면 하위 클래스에서 이를 override할 수 있습니다. 이때 상위 클래스의 init 블록에서는 하위 클래스의 override된 프로퍼티 (number)가 초기화되지 않은 상태에서 접근될 수 있습니다. 즉, 상위 클래스의 생성자가 호출될 때 하위 클래스의 프로퍼티가 아직 초기화되지 않았기 때문에, JVM의 기본값인 null이 나타날 수 있습니다.

이는 코틀린에서는 특별한 경우로 간주될 수 있으며, 실제로 객체의 생성 과정에서 비동기적으로 순서 문제가 발생한 예시라고 볼 수 있습니다. 이 상황을 방지하기 위해 상위 클래스의 초기화 블록에서 open된 프로퍼티를 사용하지 않거나, 별도의 로직을 통해 접근을 제한하는 등의 해결책이 필요합니다.

이 주제에 대해 더 자세한 설명이 필요하시다면 이미 유사한 질문이 존재할 가능성이 큽니다. 아래 링크들을 참조하시면 문제 이해에 더 큰 도움이 될 것입니다.

  1. “3. 클래스를 상속받을 때 주의할 점 질문” - 이 질문은 상위 클래스 생성자의 실행 순서와 하위 클래스의 초기화에 관한 내용이 담겨 있습니다.
  2. 관련 문서: Kotlin Official Documentation on Inheritance

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

양성빈(Robert)님의 프로필 이미지
양성빈(Robert)

작성한 질문수

질문하기