Kotlin에는 3원 연산자가 없습니다(조건 연산자)

13097 단어 KotlinJava

Kotlin 및 세 가지 연산자(조건 연산자)


구글이 안드로이드의 개발 언어로 Kotlin을 공식 지원하기 때문에 최근 화제가 된 Kotlin은 세 가지 연산자가 없다.
val max = a > b ? a : b // NG
대신 Kotlin표현식으로 간주되는 경우에서 다음과 같이 쓸 수 있다.
val max = if (a > b) a else b
그런데 자바에는 세 가지 연산자가 있는데 Kotlin이 없어서 불편하지 않습니까?
그래서 이번에는 세 가지 연산자를 강제로 만들고 싶어요

삼원 연산자 정의


Kotlin에는 ? 또는 : 연산자가 없으므로 Operator overloading 을 사용할 수 없습니다.
그러나 infix 를 사용하여 자신의 연산자를 정의할 수 있습니다.
https://kotlinlang.org/docs/reference/functions.html#infix-notation
이번에는 클래스와 infix 함수를 정의합니다. 아래와 같습니다.
data class TernaryOperation<out T>(val condition: Boolean, val value: T)

infix fun <T> Boolean.`?`(other: T) = TernaryOperation<T>(this, other)
infix fun <T> TernaryOperation<T>.`:`(other: T) = if (this.condition) this.value else other
?:는 함수명으로 사용할 수 없기 때문에 인용부호로 묶는다.
하지만 `?` 사용할 수 있고, `:` 왜 사용할 수 없는지 `:` (전각) 을 선택했다.
또한 Kotlin도 Java와 마찬가지로 함수 이름에서 일본어를 사용할 수 있지만 를 사용할 수 없습니다.
상술한 정의된 함수를 사용할 때 이런 느낌이다.
val max = (a > b) `?` a `:` b
왠지 그렇다

Java 세 가지 연산자와 다름


연산자 우선 순위


Kotlin의 infix 함수는 비교 연산자보다 우선순위가 높습니다.
https://kotlinlang.org/docs/reference/grammar.html#precedence
한편, Java의 세 연산자는 비교 연산자보다 우선순위가 낮습니다.
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html
따라서 이번에 만들어진 세 가지 연산자 중 비교 연산자 등을 사용할 경우 조건식을 괄호로 묶어야 한다.
Java
int max = a > b ? a : b; // OK
Kotlin
val max = a > b `?` a `:` b // NG

val max = (a > b) `?` a `:` b // OK
val max = (a > b) `?` a + 3 `:` b - 5 // OK

계산 공식


사카1029 씨의 평론에서 알아차렸다.감사합니다
이번에 만들어진 세 가지 연산자는 값을 전달하기 때문에 조건의 진위를 막론하고 두 개의 값이 평가된다.
Java
int value = array.length > 0 ? array[0] : -1; // OK
Kotlin
val value = array.isNotEmpty() `?` array[0] `:` -1 // arrayが空のときArrayIndexOutOfBoundsException
이것을 회피한다면 T형이 아니라 () -> T형이어야 하지만 이미 if식과 차이가 없다
data class TernaryOperation<out T>(val condition: Boolean, val value: () -> T)

infix fun <T> Boolean.`?`(other: () -> T) = TernaryOperation<T>(this, other)
infix fun <T> TernaryOperation<T>.`:`(other: () -> T) = if (this.condition) this.value() else other()

val value = array.isNotEmpty() `?` { array[0] } `:` { -1 } // OK

엘비스 연산자 모드 사용하기


다음 infix 함수를 정의합니다.
infix fun <T> Boolean.then(other: T) = if (this) other else null
엘비스 산자를 사용하면 아래와 같이 세 가지 산자를 쓸 수 있다.
val max = (a > b) then a ?: b
단, true시의 값을 사용null하면 (물론) 항상 false시의 값
val body = response.isError() then null ?: response.body // always response.body
또 아까와 마찬가지로 우선도 문제와 공식적인 평가 문제가 있다.

총결산


소재로 해보니 역시 불편하네요
자신도 Python, Kotlin 세 가지 연산자를 자주 쓰는 것이 익숙하지 않다
소감과 의견이 있으시면 댓글로 남겨주세요.

좋은 웹페이지 즐겨찾기