지난번 글에 이어 계산기 과제를 하면서 공부한 것 중 enum class 와 null safety에 대해 정리해보려고 한다.
[ 구현1. enum class ]
enum class를 이용해서 operator를 구현해보라는 리뷰를 받고 왼쪽의 코드를 오른쪽과 같이 리팩터링 했다.
enum은 단순히 값을 열거하는 존재가 아니라 enum 클래스 안에 프로퍼티나 매서드를 정의할 수 있다. 즉 ADD가 + 라는 연결을 하는 것 이외에 두 값을 받아서 합하는 연산을 할 수 있다. Evaluation 생성자에 입력 받을 연산자(operator)와 anonymous 함수를 정의해서 ADD, SUBSTRATE, MULTIPLE, DIVIDE가 어떤 연산자와 어떤 연산을 할 지 정의할 수 있다.
enum클래스도 클래스의 일종이기 때문에 매서드를 정의할수 있다. 프로퍼티 값 지정 이후에는 세미콜론(;)을 사용해서 enum 클래스 안에 정의할 매서드와 구분 해준다.
또 여기에서는 사용하지 않았지만 when을 사용해서 switch 와 같은 기능을 구현할 수 있다.
[ 구현2. enum class 사용법과 null ]
enum 클래스는 다음과 같이 매서드를 불러오거나 프로퍼티를 직접 불러와 사용할 수 있다.
Evaluation.find("+") --- "+"를 가진 ADD 객체를 리턴한다.
Evaluation.find("+").applyOperator --- 런타임 중 NPE 가 발생할 수 있다.
그런데 find의 결과 null이 나올 수 있다. 실행 중(런타임)에 null은 NPE(Null Point Exception) 에러를 발생시킨다. 그래서 null이 리턴될 수 있는 지 확인할 필요가 있는데, 코틀린은 자바의 이런 단점을 보완한 null safety한 언어이다. 코틀린은 런타임이 아닌 컴파일 시점에서 null을 검사해 실행 시점에서 발행할 수 있는 예외 가능성을 줄였다.
아래는 Evaluation.find()를 사용하면 코틀린이 자동으로 수정해주는 문법이다. "?." 는 "안전한 호출 연산자"라고 한다. 아래 코드를 보면 (1) find 결과가 null일 때 (2) applyOperator 값이 없을 때 두 번의 null 가능성을 확인한 뒤 두 값이 모두 있을 경우에만 매서드를 작동시킨다.
[ 구현3. nullalbe을 원하는 곳에서 검사하기 ]
null을 검사하는 시점을 원하는 곳에 정하면 코드가 더 간결하고 명확해질 수 있다.
계산기 validation에서 +, -, *, / 이외에 다른 문자는 들어오지 않도록 검사를 했기 때문에 enum 클래스에서 사칙연산을 찾지 못해 null이 반환되는 경우는 없을 것이라고 생각할 수 있다. 따라서 "?"를 제거해 Evaluation에서 null 값은 리턴되지 않는다고 알려준다. 그러면 ?. 연산자를 단순 dot(.) 연산자로 바꿀 수 있다. 물론 생각이 틀릴 수도 있다. 실행 중에 null이 들어 올 수도 있다. 그래서 아래와 같이 Safe call on non-null receiver will have nullable type in future release (지금은 non-null이지만 nullable type이 들어올 수도 있어) 라는 경고를 한다.
[ 구현 4. non-null에 에러 처리 ]
위에서 말한 NPE 불상사가 일어나지 않도록 만일의 경우를 대비해 .throw로 에러를 처리한다. 사칙 연산을 찾을 수 없다면 다음으로 넘어가지 말고 INVALID_OPERATOR 에러를 던진다.
이외에 null safety와 관련된 문법을 추가적으로 정리해보면,
널 아님 단언: !! 어떤 값이든 널이 될 수 없는 타입으로 (강제로) 바꿀 수 있다. "나는 이 값이 null이 아님을 잘 알고 있다. 내가 잘못 생각했다면 예외가 발생해도 감수하겠다."라고 말하는 것이다. 아마도 !!가 약간 무례해 보인다는 사실을 눈치챘을 것이다. !! 기호는 마치 컴파일러에게 소리를 지르는 것 같은 느낌이 든다. 사실 이는 의도한 것이다. 코틀린 설계자들은 컴파일러가 검증할 수 없는 단언을 사용하기보다는 더 나은 방법을 찾아보라는 의도를 넌지시 표현하려고 !!라는 못생긴 기호를 택했다.
아래와 같은 코드에서 에러가 나면 !!가 선언된 곳에서 null이 발견되었다는 의미로 NPE가 난다.
fun ignoreNulls(s: String?){
val sNotNull: String = s!! --- NPE 에러가 이 지점을 가르킨다.
println(sNotNull.length)
}
let 함수: 아주 긴 식이 있고 그 값이 널이 아닐 때 수행해야하는 로직이 있을 때 let을 쓰면 좋다.
아래 같이 작성하면 email이 입력된 경우에만 이메일을 보낸다.
var email: String? = "yole@example.com"
email?.let { sendEmailTo(it) }
http://www.yes24.com/Product/Goods/55148593
Kotlin in Action - YES24
코틀린이 안드로이드 공식 언어가 되면서 관심이 커졌다. 이 책은 코틀린 언어를 개발한 젯브레인의 코틀린 컴파일러 개발자들이 직접 쓴 일종의 공식 서적이라 할 수 있다. 코틀린 언어의 가장
www.yes24.com
'백엔드 개발 > 백엔드 일기' 카테고리의 다른 글
#014. 백엔드 성장일기: 코드리뷰어를 지치지 않게 하는 커밋하기 (2) | 2022.05.18 |
---|---|
Q001. 구글 계정을 만들 때, 이미 있는 아이디인지 어떻게 빠르게 알 수 있을까? (0) | 2022.05.14 |
#012. 백엔드 성장일기: [넥스트 스탭] 코틀린의 특징을 살려 리팩터링 하기 (0) | 2022.05.12 |
#011. 백엔드 성장일기: PostGreSQL에서 🤦♀️의 글자수 확인하기 (0) | 2022.05.07 |
#010. 백엔드 성장일기: 테이블 스키마 작성하기 (2) | 2022.05.03 |