[kotlin] non-null 타입 반환의 타입불일치에 대해서 질문좀드려요

조회수 418회
fun getTitle(): String = titleData.joinToString(" / ")

title = bpCV?.getTitle().toString() // 1 toString없으면 에러
bpCV?.apply { title = getTitle() } // 2
title = run { bpCV?.getTitle() } // 3 error. 타입 불일치, 엘비스 연산자 사용가능
title = bpCV?.run { getTitle() } // 4 error. 타입 불일치, 엘비스 연산자 사용가능

String 타입의 title에 getTitle의 반환값을 저장하는 코드인데요

1번 2번은 에러가 안납니다. 1번같은 경우에는 toString() 없으면 타입 불일치로 에러가나는데..

이 타입 불일치 에러에서 궁금한게..

제가 getTitle()이 String을 반환한다고 명시했잖아요? 그리고 title도 String 타입이고.

그런데 타입 불일치 에러로 저 메소드에서 찾은 타입은 String? 이라구 나와요..

이게 getTitle()이 String을 반환한다고 명시했으면 타입이 맞아야하는것 아닌가요?

joinToString()도 String타입을 반환한다고 되어있는데..이게 그럼 확정적으로 String 타입이 반환되어야하는게 아닌지..

왜 불일치를 띄우는지 이해가 잘가질 않아요.

혹시 그런거에 관계없이 반환하는 값이 null일 가능성이 있기때문인가요?

그래서 1번같은 경우에는 getTitle()해서 toString으로 해야지 null값이라도 toString 인해서 모든 값에 대해 String 타입으로 반환시키는건가요..

2번은 apply를 사용했는데 이건 그 apply가 자신의 프로퍼티같은거 초기화할때 써준다고해서 별로 좋은 방법같지는 않은데 어떤가요?

3,4번처럼 코드를 작성하는게 좋은거같은데 이거 어떻게 String을 보장해야하는지 모르겠어요..

1 답변

  • 좋아요

    2

    싫어요
    채택 취소하기

    질문자님께서는 Kotlin 의 safety call 의 특성과 toString() 반환 타입과 getTitle() 반환 타입이 동일한 것에 있어서 타입 불일치가 발생하는 원인에 혼동이 있으신 것 같습니다 :)

    첫번째로, bpCV?.getTitle() 와 같이 safety call 을 할 경우 bpCVnullable 을 의미하므로 bpCVnull 이면 해당 인스턴스에 참조가 불가능 할 것이며 getTitle() 의 반환 타입과 관계없이 null 을 반환 합니다. 따라서 bpCV?.getTitle() 자체는 nullable 을 의미합니다. 따라서 titlenon-null type 이라면 타입 불일치가 발생 하는 것이 맞습니다. 이렇게 safety callNullPointerException 에 대한 안정성을 보장하기 위해 사용 됩니다.

    두번째로 toString() 내부 코드를 살펴 볼게요.

    /**
     * Returns a string representation of the object. Can be called with a null receiver, in which case
     * it returns the string "null".
     */
    public fun Any?.toString(): String
    

    bpCV?.getTitle()nullable 을 의미하지만 위의 toString()Any? 와 같이 null receiver 에 대한 확장 함수 이므로 toString() 은 그대로 호출될 것이며 반환 값이 non-null type 이기 때문에 title 과 타입이 일치합니다. kotlin extensions 에 대해 참고 해보시면 도움이 되실 것 같습니다.


    다음으로,

    apply가 자신의 프로퍼티같은거 초기화할때 써준다고해서 별로 좋은 방법같지는 않은데 어떤가요?

    apply 의 구성을 보면 프로퍼티 초기화를 할때 용이하게 사용 될 수 있는 것은 맞지만, 꼭 해당 상황에 한정하여 사용되어야만 하는 것은 아닙니다.

    이와 같은 scope 함수들은 특정 람다식을 활용하여 임시 블록을 생성 한 뒤 코드를 더 간결하고 읽기 쉽게 만들기 위해 제공 되는 것이므로, 해당 함수들의 특성을 살펴보시고 필요한 곳에 적절히 사용 하시면 됩니다.

    따라서 2번 과 같이 bpCV?.apply { title = getTitle() } 코드도 괜찮은 방법이라고 볼 수 있습니다. 또한 엘비스 연산자를 사용하여 처리 할 수도 있겠네요.

    title = bpCV?.getTitle() ?: "타이틀"
    title = bpCV?.gettitle() ?: throw Exception("Unknown title")
    

    3, 4번에서 타입 불일치가 발생 하는 부분은 위에 말씀 드린 내용으로 이해가 되셨을 것이라고 생각 됩니다.

    • (•́ ✖ •̀)
      알 수 없는 사용자

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)