[Kotlin Deep Dive] 5. Nullable, !!, let 함수, Nullable 타입 확장, 읽기 전용 컬렉션의 스레드 안전, 시그니처

akim·2022년 11월 25일
0

Kotlin Deep Dive

목록 보기
5/9
post-thumbnail

1. Nullable 타입으로 무엇을 할 수 있을까?

Nullable 타입은 수행할 수 있는 연산이 많이 제한되기는 하지만 널 값과 비교할 수 있다는 장점이 있다.

이게 왜 장점일까?

Nullable이 아닌 경우 널 값에 의해 오류가 나더라도 그냥 일반 오류 메세지를 띄우기 때문에 개발자 입장에서는 무엇이 문제인지 알기 힘들다. 그러나 Nullable의 경우 명확히 NPE을 발생시키기 때문에 널에 의한 오류임을 바로 알 수 있게 된다.

그리고 컴파일러는 이를 기억해서 non null임이 확실한 영역에서는 non null 값처럼 사용할 수 있도록 한다.

2. !!의 활용

!!가 이름이 널 아님 단언이라고 해서 무조건 NPE를 피할 수 있는 것은 아니다.

널 아님 단언을 사용하더라도 값이 널일때는 NPE를 던질 수 있다. 따라서 !!의 활용은 신중해야 한다.

예를 들어 어떤 함수에서 값이 널인지 검사를 한 후에 명확히 non null인게 결정되면 나중에 호출된 함수 안에서 이 값을 안전하게 사용할 수 있다는 보증으로 !!를 써주는 식이다. 이렇게 하게 되면 호출된 함수가 굳이 널 검사를 수행하지 않도록 해주어 더 효율적으로 코드를 쓸 수 있다.

3. let 함수

scope 함수

스코프 함수는 특정 객체의 컨텍스트 내에서 특정 동작 (프로퍼티 초기화, 활용 등)을 실행하기 위한 목적만을 가진 함수다.

이 스코프 내에서에서는 객체의 이름을 통해 일일이 참조할 필요 없이 객체를 접근하고 핸들링할 수 있어 편리하다는 장점이 있다.

코틀린이 제공하는 스코프 함수는 총 5가지로, apply, run , with , alse , let으로 이루어져 있다.

(출처: https://medium.com/@fatihcoskun/kotlin-scoping-functions-apply-vs-with-let-also-run-816e4efb75f5)

let 함수

수신 객체를 접근할 때 it을 사용할 수 있도록 하는 스코프 함수의 일종이다.

it을 사용해야 하는 이유는 무엇일까?

해당 클래스 밖의 main() 스코프 내에 인스턴스 프로퍼티와 이름이 같은 변수가 있는 경우 상위 스코프인 main() 스코프의 동명의 변수를 참조하게 된다. 실제로 개발을 하다보면 변수 명을 짓는 게 여간 일이 아니므로... 이와 같은 혼란이 생길 수도 있다.

바로 이러한 혼란을 방지하기 위해 it이라는 키워드가 필요한 것이다. it 키워드에 참조 연산자를 통해 프로퍼티 및 함수를 접근하면 해당 스코프 내에서 안전하게 참조가 가능해진다.

let 함수의 활용 예시

  • 지정된 값이 null 이 아닌 경우에 코드를 실행해야 하는 경우
  • Nullable 객체를 다른 타입의 변수로 변환해야 하는 경우
  • 단일 지역 변수의 범위를 제한하는 경우

4. Nullable 타입 확장

어떤 메서드를 호출하기 전에 수신 객체 역할을 하는 변수가 널이 될 수 없다고 보장하는 대신 직접 변수에 대해 메서드를 호출해도 확장 함수인 메서드가 알아서 널을 처리해준다.

즉, 메서드 호출 전에 그 변수가 non null이라고 보장해봤자 아무 의미 없고, 확장 함수인 메서드가 알아서 널 값에 대한 체크를 한다는 것이다.

그러나 자바의 경우 애초에 확장을 정의할 수 없기에 널이 될 수 있는 값에 대해 확장 함수를 호출할 수 없다. 따라서 자바의 경우 수신 객체의 타입은 항상 non null 타입이고, 메서드 안의 this는 해당 수신 객체를 가리키므로 역시 항상 non null 타입이다.

하지만 코틀린의 경우 nullable을 수신 객체로 하여 확장 함수를 정의할 수 있고, 이 경우 수신 객체를 가리키는 this 역시 nullable이 될 수 있다.

결국 null 값을 다룰 수 있다는 점에서 nullable 타입 확장은 강력한 기능이라고 할 수 있다.

5. 읽기 전용 컬렉션의 스레드 안전

내가 아무리 운전을 조심히 한다고 하더라도 남이 와서 들이받으면 결론적으로는 사고가 나게 난다.

"읽기 전용 컬렉션이 스레드 안전을 보장하는 것은 아니다." 라는 말은 위 한 문장으로 설명이 가능하다.

내가 읽기 전용 컬렉션으로 어떤 데이터에 접근하고 있다고 하더라도 다른 곳에서 변경 가능한 컬렉션으로 접근을 하고 있다면 해당 데이터가 변경되어 의도와 다르게 잘못된 값을 읽어올 수도 있는 것이다.

따라서 읽기 전용 컬렉션을 이용한다고 하더라도 항상 스레드 안전한 것은 아니다.

6. 시그니처

함수의 시그니처는 일반적으로 함수의 원형에 명시되는 매개변수 리스트를 가리킨다. 만약 두 함수가 매개변수의 개수와 타입이 모두 같다면 두 함수의 시그니처는 같다고 할 수 있다.

시그니처는 다음을 포함할 수 있다. (언어마다 조금씩 다르다.)

  • 파라미터와 그들의 타입
  • 반환값과 타입
  • 던져지거나 콜백으로 반환되는 exceptions
  • 객체 지향 프로그램에서 메소드의 접근 권한에 대한 정보 (public 등의 키워드들)

간단하게 생각해서 그냥 함수의 맨 윗줄이라고 생각하면 된다.

profile
학교 다니는 개발자

0개의 댓글