Tương đương với biểu thức này trong Kotlin là gì?
a ? b : c
Đây không phải là mã hợp lệ trong Kotlin.
Tương đương với biểu thức này trong Kotlin là gì?
a ? b : c
Đây không phải là mã hợp lệ trong Kotlin.
Câu trả lời:
Trong Kotlin, các if
câu lệnh là biểu thức. Vì vậy, đoạn mã sau là tương đương:
if (a) b else c
Sự phân biệt giữa biểu thức và tuyên bố là quan trọng ở đây. Trong Java / C # / JavaScript, if
tạo thành một câu lệnh, nghĩa là nó không phân giải thành một giá trị. Cụ thể hơn, bạn không thể gán nó cho một biến.
// Valid Kotlin, but invalid Java/C#/JavaScript
var v = if (a) b else c
Nếu bạn đến từ một ngôn ngữ if
là một tuyên bố, điều này có vẻ không tự nhiên nhưng cảm giác đó sẽ sớm lắng xuống.
when
.
x = a==b
b + if (a) c else d
so với b + (c if (a) else d)
cái sau đòi hỏi dấu ngoặc đơn bổ sung. bởi vì c
không được bao bọc bởi các điều kiện và else
.
Bạn có thể định nghĩa của riêng bạn Boolean
chức năng mở rộng mà lợi nhuận null
khi Boolean
là false
để cung cấp một cấu trúc tương tự như các nhà điều hành ternary:
infix fun <T> Boolean.then(param: T): T? = if (this) param else null
Điều này sẽ làm cho một a ? b : c
biểu thức dịch thành a then b ?: c
, như vậy:
println(condition then "yes" ?: "no")
Cập nhật: Nhưng để thực hiện một số chuyển đổi có điều kiện giống Java hơn, bạn sẽ cần một cái gì đó tương tự
infix fun <T> Boolean.then(param: () -> T): T? = if (this) param() else null
println(condition then { "yes" } ?: "no")
chú ý đến lambda. tính toán nội dung của nó nên được hoãn lại cho đến khi chúng tôi đảm bảocondition
làtrue
Điều này có vẻ vụng về, đó là lý do tại sao có yêu cầu đòi hỏi cao tồn tại để chuyển toán tử ternary Java vào Kotlin
infix inline fun<T> Boolean.then(param: ()->T):T? = if(this) param() else null
true then { null } ?: "not-null"
?:
nhà điều hành ở đây là elvis-operator
: kotlinlang.org/docs/reference/null-safe.html#elvis-operator
if (a) b else c
là những gì bạn có thể sử dụng thay vì biểu thức toán tử ternary a ? b : c
.
Trong Kotlin, nhiều câu lệnh điều khiển bao gồm if
, when
hoặc thậm chí try
có thể được sử dụng làm biểu thức . Điều này có nghĩa là những cái đó có thể có một kết quả có thể được gán cho một biến, được trả về từ một hàm, v.v.
Do kết quả của các biểu thức của Kotlin, ngôn ngữ không thực sự cần toán tử ternary .
if (a) b else c
là những gì bạn có thể sử dụng thay vì biểu thức toán tử ternary a ? b : c
.
Tôi nghĩ ý tưởng là biểu thức trước dễ đọc hơn vì mọi người đều biết ifelse
nó làm gì , trong khi đó ? :
vẫn chưa rõ ràng nếu bạn chưa quen với cú pháp.
Tuy nhiên, tôi phải thừa nhận rằng tôi thường bỏ lỡ các nhà điều hành ternary thuận tiện hơn.
Các lựa chọn thay thế khác
khi nào
Bạn cũng có thể thấy các when
cấu trúc được sử dụng trong Kotlin khi các điều kiện được kiểm tra. Đó cũng là một cách để thể hiện thác nếu khác theo cách khác. Sau đây tương ứng với ví dụ OTs.
when(a) {
true -> b
false -> c
}
Tiện ích mở rộng
Như nhiều ví dụ hay ( Nhà điều hành có điều kiện của Kotlin Ternary ) trong các câu trả lời khác cho thấy, các tiện ích mở rộng cũng có thể giúp giải quyết trường hợp sử dụng của bạn.
Đối với bản thân tôi, tôi sử dụng các chức năng mở rộng sau:
fun T?.or<T>(default: T): T = if (this == null) default else this
fun T?.or<T>(compute: () -> T): T = if (this == null) compute() else this
Đầu tiên sẽ trả về giá trị mặc định được cung cấp trong trường hợp đối tượng bằng null. Thứ hai sẽ đánh giá biểu thức được cung cấp trong lambda trong trường hợp tương tự.
Sử dụng:
1) e?.getMessage().or("unknown")
2) obj?.lastMessage?.timestamp.or { Date() }
Cá nhân đối với tôi mã ở trên dễ đọc hơn if
xây dựng nội tuyến
e.getMessage() ?: "unknown"
. Thứ hai có thể được thể hiện làobj?.lastMessage?.timestamp ?: { Date() }()
Java tương đương với toán tử ternary
a ? b : c
là một IF đơn giản trong Kotlin trong một dòng
if(a) b else c
không có toán tử ternary (điều kiện? sau đó: khác), bởi vì bình thường nếu hoạt động tốt trong vai trò này.
https://kotlinlang.org/docs/reference/control-flow.html#if-expression
Trường hợp đặc biệt để so sánh Null
bạn có thể sử dụng toán tử Elvis
if ( a != null ) a else b
// equivalent to
a ?: b
Không có toán tử ternary trong kotlin, vì if else
khối trả về giá trị
vì vậy, bạn có thể làm:
val max = if (a > b) a else b
thay vì javamax = (a > b) ? b : c
Chúng tôi cũng có thể sử dụng when
xây dựng, nó cũng trả về giá trị:
val max = when(a > b) {
true -> a
false -> b
}
Đây là liên kết cho tài liệu kotlin: Control Flow: if, when, for, while
Trong Kotlin,
if
là một biểu thức, tức là nó trả về một giá trị. Do đó, không có toán tử ternary(condition ? then : else)
, vì bình thường nếu hoạt động tốt trong vai trò này. nguồn thủ công từ đây
// Traditional usage
var max = a
if (a < b) max = b
// With else
var max: Int
if (a > b) {
max = a
} else {
max = b
}
// As expression
val max = if (a > b) a else b
Một số trường hợp góc không được đề cập trong câu trả lời khác.
Vì sự xuất hiện của Take If trong Kotlin 1.1 , toán tử ternary a ? b : c
cũng có thể được biểu thị như sau:
b.takeIf { a } ?: c
Điều này càng trở nên ngắn hơn trong trường hợp c là null
:
b.takeIf { a }
Cũng lưu ý rằng điển hình trong thế giới Java kiểm tra null như value != null ? value : defaultValue
dịch trong Kotlin ý thức hệ sang value ?: defaultValue
.
Tương tự a != null ? b : c
có thể được dịch sang a?.let { b } ?: c
.
b.takeIf { a } ?: c
ngắn hơn và dễ đọc hơn if (a) b else c
? Toán tử Terneray chắc chắn là một tính năng bị thiếu trong Kotlin vì tên biến và điều kiện có thể dài và khiến bạn chia dòng là xấu
takeIf
luôn luôn đánh giá trường hợp thực (ở đây a
). Biểu thức đó không chỉ có thể được tính toán một cách vô ích nếu a
tình cờ là sai, mà bạn không thể hưởng lợi từ các diễn viên thông minh à la if (a is Int) { a + 3 }
.
{ a }
là một lambda đánh giá lười biếng.
b
)". Nhưng thậm chí { a }
, trong khi lười biếng, phải được đánh giá để xác định kết quả của biểu thức.
NHIỆM VỤ :
Hãy xem xét ví dụ sau:
if (!answer.isSuccessful()) {
result = "wrong"
} else {
result = answer.body().string()
}
return result
Chúng ta cần tương đương như sau trong Kotlin:
return (! answer.isSuccessful ())
?
"sai":
answer.body (). string ()
GIẢI PHÁP :
1.a . Bạn có thể sử dụng if-expression
trong Kotlin:
return if (!answer.isSuccessful()) "wrong" else answer.body().string()
1.b . Nó có thể tốt hơn nhiều nếu bạn lật nó if-expression
(hãy làm mà không có not
):
return if (answer.isSuccessful()) answer.body().string() else "wrong"
2 . Nhà điều hành Elvis của Kotlin ?:
có thể làm một công việc thậm chí còn tốt hơn:
return answer.body()?.string() ?: "wrong"
3 . Hoặc sử dụng một Extension function
cho Answer
lớp tương ứng :
fun Answer.bodyOrNull(): Body? = if (isSuccessful()) body() else null
4 . Sử dụng Extension function
bạn có thể giảm mã nhờ Elvis operator
:
return answer.bodyOrNull()?.string() ?: "wrong"
5 . Hoặc chỉ sử dụng when
toán tử:
when (!answer.isSuccessful()) {
parseInt(str) -> result = "wrong"
else -> result = answer.body().string()
}
Hi vọng điêu nay co ich.
khi thay thế toán tử chuyển đổi của các ngôn ngữ giống như C. Ở dạng đơn giản nhất, nó trông như thế này
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> {
print("x is neither 1 nor 2")
}
}
when
dưới dạng một tuyên bố, không phải là một biểu thức. Một so sánh phù hợp hơn với các biểu thức điều kiện ternary sẽ là mỗi nhánh trả về một giá trị, sao cho toàn bộ khi biểu thức ước lượng thành một giá trị (như xảy ra với các điều kiện ternary).
Không có nhà điều hành ternary trong Kotlin. Có vẻ như có vấn đề ở cái nhìn đầu tiên. Nhưng nghĩ rằng chúng ta có thể làm điều đó với nội tuyến nếu câu lệnh khác bởi vì đây là biểu thức ở đây. Đơn giản là chúng ta phải làm -
var number = if(n>0) "Positive" else "Negetive"
Ở đây chúng ta có thể khác nếu chặn quá nhiều như chúng ta cần. Giống-
var number = if(n>0) "Positive" else if(n<0) "Negative" else "Zero"
Vì vậy, dòng này là rất đơn giản và dễ đọc hơn so với toán tử ternary. Khi chúng ta sử dụng nhiều hơn một toán tử ternary trong java thì có vẻ khủng khiếp. Nhưng ở đây chúng tôi có một cú pháp rõ ràng. thậm chí chúng ta có thể viết nó trong nhiều dòng quá.
Bạn có thể sử dụng var a= if (a) b else c
thay cho toán tử ternary.
Một khái niệm hay khác về kotlin là Elvis operater. Bạn không cần phải kiểm tra null mỗi lần.
val l = b?.length ?: -1
Điều này sẽ trả về độ dài nếu b không null nếu không nó thực thi câu lệnh bên phải.
như Drew Noakes đã trích dẫn, kotlin sử dụng câu lệnh if làm biểu thức, do đó Toán tử điều kiện Ternary không còn cần thiết nữa,
nhưng với chức năng mở rộng và nạp chồng, bạn có thể tự thực hiện, đây là một ví dụ
infix fun <T> Boolean.then(value: T?) = TernaryExpression(this, value)
class TernaryExpression<out T>(val flag: Boolean, val truly: T?) {
infix fun <T> or(falsy: T?) = if (flag) truly else falsy
}
sau đó sử dụng nó như thế này
val grade = 90
val clazz = (grade > 80) then "A" or "B"
Một cách tiếp cận thú vị khác là sử dụng when
:
when(a) {
true -> b
false -> b
}
Có thể khá tiện dụng trong một số tình huống phức tạp hơn. Và thành thật mà nói, nó dễ đọc đối với tôi hơnif ... else ...
Bạn có thể làm điều đó theo nhiều cách trong Kotlin
Sử dụng nếu
if(a) b else c
Sử dụng khi
when (a) {
true -> print("value b")
false -> print("value c")
else -> {
print("default return in any other case")
}
}
An toàn Null
val a = b ?: c
Không có hoạt động ternary trong Kotlin, nhưng có một số cách thú vị để làm việc xung quanh đó. Như những người khác đã chỉ ra, một bản dịch trực tiếp sang Kotlin sẽ như thế này:
val x = if (condition) result1 else result2
Nhưng, cá nhân, tôi nghĩ rằng có thể có một chút lộn xộn và khó đọc. Có một số tùy chọn khác được xây dựng trong thư viện. Bạn có thể sử dụng Take If {} với toán tử elvis:
val x = result1.takeIf { condition } ?: result2
Điều đang xảy ra là lệnh Take If {} trả về kết quả1 hoặc null của bạn và toán tử elvis xử lý tùy chọn null. Có một số tùy chọn bổ sung, ví dụ: TakeUnless {}:
val x = result1.takeUnless { condition } ?: result2
Ngôn ngữ rất rõ ràng, bạn biết những gì đang làm.
Nếu đó là một điều kiện thường được sử dụng, bạn cũng có thể làm điều gì đó thú vị như sử dụng phương thức mở rộng nội tuyến. Ví dụ, giả sử chúng tôi muốn theo dõi điểm số trò chơi dưới dạng Int, và chúng tôi muốn luôn trả về 0 nếu không đáp ứng một điều kiện nhất định:
inline fun Int.zeroIfFalse(func: () -> Boolean) : Int = if (!func.invoke()) 0 else this
Ok, điều đó có vẻ xấu. Nhưng hãy xem nó trông như thế nào khi nó được sử dụng:
var score = 0
val twoPointer = 2
val threePointer = 3
score += twoPointer.zeroIfFalse { scoreCondition }
score += threePointer.zeroIfFalse { scoreCondition }
Như bạn có thể thấy, Kotlin cung cấp rất nhiều tính linh hoạt trong cách bạn chọn để thể hiện mã của mình. Có vô số biến thể của các ví dụ của tôi và có lẽ là những cách tôi chưa từng khám phá. Tôi hi vọng cái này giúp được!
takeIf
là lựa chọn yêu thích của tôi thực sự, rất thanh lịch.
Hãy nhớ toán tử Ternary và toán tử Elvis giữ các ý nghĩa riêng biệt trong Kotlin không giống như trong nhiều ngôn ngữ phổ biến. Làm expression? value1: value2
sẽ cung cấp cho bạn những từ xấu của trình biên dịch Kotlin , không giống như bất kỳ ngôn ngữ nào khác vì không có toán tử tạm thời trong Kotlin như được đề cập trong các tài liệu chính thức . Lý do là các câu lệnh if, when và try-Catch tự trả về các giá trị.
Vì vậy, làm expression? value1: value2
có thể được thay thế bởi
val max = if (a> b) print ("Chọn a") khác in ("Chọn b")
Các nhà điều hành Elvis rằng Kotlin có, chỉ hoạt động trong trường hợp nullable biến cũ .:
Nếu tôi làm một cái gì đó như
value3 = value1 ?: value2
sau đó nếu value1 là null thì value2 sẽ được trả về nếu không value1 sẽ được trả về.
Một sự hiểu biết rõ ràng hơn có thể đạt được từ những câu trả lời này .
Bạn có thể sử dụng if
biểu thức cho điều này trong Kotlin. Trong Kotlin if
là một biểu thức có giá trị kết quả. Vì vậy, trong Kotlin chúng ta có thể viết
fun max(a: Int, b: Int) = if (a > b) a else b
và trong Java chúng ta có thể đạt được điều tương tự nhưng với mã lớn hơn
int max(int a, int b) {
return a > b ? a : b
}
Nếu bạn không sử dụng ký hiệu chuẩn nào, bạn cũng có thể tạo / mô phỏng nó bằng infix với một cái gì đó như thế này:
tạo một lớp để giữ mục tiêu và kết quả của bạn:
data class Ternary<T>(val target: T, val result: Boolean)
tạo một số hàm infix để mô phỏng thao tác ternary
infix fun <T> Boolean.then(target: T): Ternary<T> {
return Ternary(target, this)
}
infix fun <T> Ternary<T>.or(target: T): T {
return if (this.result) this.target else target
}
Sau đó, bạn sẽ có thể sử dụng nó như thế này:
val collection: List<Int> = mutableListOf(1, 2, 3, 4)
var exampleOne = collection.isEmpty() then "yes" or "no"
var exampleTwo = (collection.isNotEmpty() && collection.contains(2)) then "yes" or "no"
var exampleThree = collection.contains(1) then "yes" or "no"
Một cách tiếp cận ngắn khác để sử dụng
val value : String = "Kotlin"
value ?: ""
Ở đây kotlin tự kiểm tra giá trị null và nếu nó là null thì nó chuyển giá trị chuỗi rỗng.
Tại sao người ta sẽ sử dụng một cái gì đó như thế này:
when(a) {
true -> b
false -> b
}
khi bạn thực sự có thể sử dụng một cái gì đó như thế này ( a
là boolean trong trường hợp này):
when {
a -> b
else -> b
}
? and :
mâu thuẫn với khai báo nullable / type hơn là kiểm tra kiểu. Ngoài ra tôi không thấy bất kỳ lý do. Tôi nghĩ rằng ai đó chắc chắn đã đặt một số suy nghĩ, nếu có kiểm tra điều kiện if-if nội tuyến. Hãy chờ xem các phiên bản trong tương lai.
Khi làm việc với áp dụng (), hãy để có vẻ rất tiện dụng khi xử lý các hoạt động ternary, vì nó thanh lịch hơn và cung cấp cho bạn phòng
val columns: List<String> = ...
val band = Band().apply {
name = columns[0]
album = columns[1]
year = columns[2].takeIf { it.isNotEmpty() }?.let { it.toInt() } ?: 0
}
Với các hàm infix sau đây, tôi có thể bao quát nhiều trường hợp sử dụng phổ biến gần giống như cách nó có thể được thực hiện trong Python:
class TestKotlinTernaryConditionalOperator {
@Test
fun testAndOrInfixFunctions() {
Assertions.assertThat(true and "yes" or "no").isEqualTo("yes")
Assertions.assertThat(false and "yes" or "no").isEqualTo("no")
Assertions.assertThat("A" and "yes" or "no").isEqualTo("yes")
Assertions.assertThat("" and "yes" or "no").isEqualTo("no")
Assertions.assertThat(1 and "yes" or "no").isEqualTo("yes")
Assertions.assertThat(0 and "yes" or "no").isEqualTo("no")
Assertions.assertThat(Date() and "yes" or "no").isEqualTo("yes")
@Suppress("CAST_NEVER_SUCCEEDS")
Assertions.assertThat(null as Date? and "yes" or "no").isEqualTo("no")
}
}
infix fun <E> Boolean?.and(other: E?): E? = if (this == true) other else null
infix fun <E> CharSequence?.and(other: E?): E? = if (!(this ?: "").isEmpty()) other else null
infix fun <E> Number?.and(other: E?): E? = if (this?.toInt() ?: 0 != 0) other else null
infix fun <E> Any?.and(other: E?): E? = if (this != null) other else null
infix fun <E> E?.or(other: E?): E? = this ?: other
Không có toán tử ternary trong Kotlin, đóng nhất là hai trường hợp dưới đây,
val a = true if(a) print("A is true") else print("A is false")
Nếu biểu thức ở bên trái của ?: Không phải là null, toán tử elvis trả về nó, nếu không nó sẽ trả lại biểu thức ở bên phải. Lưu ý rằng biểu thức phía bên phải chỉ được ước tính nếu phía bên trái là null.
val name = node.getName() ?: throw IllegalArgumentException("name expected")
ví dụ: var Energy: Int = data? .get (vị trí) ?. năng lượng? .toInt () ?: 0
Trong kotlin nếu bạn đang sử dụng ?: Nó sẽ hoạt động như thế nào nếu câu lệnh sẽ trả về null sau đó ?: 0 sẽ mất 0 hoặc bất cứ điều gì bạn có viết bên này.
Trong Kotlin, bạn có thể sử dụng thao tác ternary như thế này: val x = if(a) "add b" else "add c"
Sau một số nghiên cứu về các ý tưởng khác, tôi đã nhận được toán tử ternary sau:
infix fun <T : Any> Boolean.yes(trueValue: T): T? = if (this) trueValue else null
infix fun <T : Any> T?.no(falseValue: T): T = this ?: falseValue
Ví dụ (chạy ở đây ):
fun main() {
run {
val cond = true
val result = cond yes "True!" no "False!"
println("ternary test($cond): $result")
}
run {
val cond = false
val result = cond yes "True!" no "False!"
println("ternary test($cond): $result")
}
}
Phiên bản này trôi chảy và không xung đột với toán tử hợp nhất null.
then
thay vì yes
.