อะไรคือสิ่งที่เทียบเท่ากับการแสดงออกใน Kotlin นี้?
a ? b : c
นี่ไม่ใช่รหัสที่ถูกต้องใน Kotlin
อะไรคือสิ่งที่เทียบเท่ากับการแสดงออกใน Kotlin นี้?
a ? b : c
นี่ไม่ใช่รหัสที่ถูกต้องใน Kotlin
คำตอบ:
ใน Kotlin if
คำสั่งเป็นนิพจน์ ดังนั้นรหัสต่อไปนี้เทียบเท่า:
if (a) b else c
ความแตกต่างระหว่างการแสดงออกและข้อความเป็นสิ่งสำคัญที่นี่ ใน Java / C # / JavaScript ให้if
สร้างคำสั่งซึ่งหมายความว่าจะไม่สามารถแก้ไขค่าได้ ยิ่งเป็นรูปธรรมคุณไม่สามารถกำหนดให้กับตัวแปรได้
// Valid Kotlin, but invalid Java/C#/JavaScript
var v = if (a) b else c
หากคุณมาจากภาษาที่if
มีคำแถลงสิ่งนี้อาจดูผิดธรรมชาติ แต่ความรู้สึกนั้นก็จะหายไปในไม่ช้า
when
นอกจากนี้คุณยังสามารถใช้
x = a==b
b + if (a) c else d
vs. b + (c if (a) else d)
หลังหนึ่งต้องการวงเล็บเพิ่มเติม เพราะไม่ได้ถูกล้อมรอบด้วยสภาพและc
else
คุณสามารถกำหนดBoolean
ฟังก์ชั่นส่วนขยายของคุณเองที่ส่งกลับnull
เมื่อBoolean
คือfalse
การให้โครงสร้างคล้ายกับผู้ประกอบการที่ประกอบไปด้วย:
infix fun <T> Boolean.then(param: T): T? = if (this) param else null
สิ่งนี้จะทำให้การa ? b : c
แสดงออกเป็นa then b ?: c
เช่น:
println(condition then "yes" ?: "no")
อัปเดต: แต่หากต้องการสลับเงื่อนไขแบบคล้าย Java คุณจะต้องมีสิ่งนั้น
infix fun <T> Boolean.then(param: () -> T): T? = if (this) param() else null
println(condition then { "yes" } ?: "no")
ให้ความสนใจกับแลมบ์ดา คำนวณเนื้อหาควรจะเลื่อนออกไปจนกว่าเราจะตรวจสอบให้แน่ใจcondition
คือtrue
อันนี้ดูเงอะงะนั่นคือเหตุผลที่มีคำขอที่มีความต้องการสูงในการพอร์ตผู้ประกอบการที่สามของจาวาเข้าไปใน Kotlin
infix inline fun<T> Boolean.then(param: ()->T):T? = if(this) param() else null
true then { null } ?: "not-null"
?:
ผู้ดำเนินการที่นี่คือelvis-operator
: kotlinlang.org/docs/reference/null-safety.html#elvis-operator
if (a) b else c
คือสิ่งที่คุณสามารถใช้แทนนิพจน์ตัวดำเนินการแบบไตรa ? b : c
ภาค
ใน Kotlin งบจำนวนมากรวมทั้งการควบคุมif
, when
หรือแม้กระทั่งtry
สามารถใช้เป็นสำนวนที่ ซึ่งหมายความว่าสิ่งเหล่านั้นสามารถมีผลลัพธ์ที่สามารถกำหนดให้กับตัวแปรส่งคืนจากฟังก์ชัน ฯลฯ
เป็นผลมาจากการแสดงออกของ Kotlin ภาษาไม่จำเป็นต้องดำเนินการประกอบไปด้วย
if (a) b else c
คือสิ่งที่คุณสามารถใช้แทนนิพจน์ตัวดำเนินการแบบไตรa ? b : c
ภาค
ฉันคิดว่าความคิดคือการแสดงออกในอดีตนั้นสามารถอ่านได้มากขึ้นเนื่องจากทุกคนรู้ว่าสิ่งifelse
ใดในขณะที่? :
ค่อนข้างชัดเจนถ้าคุณไม่คุ้นเคยกับไวยากรณ์อยู่แล้ว
อย่างไรก็ตามฉันต้องยอมรับว่าฉันมักจะพลาดผู้ประกอบการที่สะดวกมากขึ้น
ทางเลือกอื่น ๆ
เมื่อไหร่
คุณอาจเห็นwhen
โครงสร้างที่ใช้ใน Kotlin เมื่อตรวจสอบเงื่อนไข นอกจากนี้ยังเป็นวิธีในการแสดงให้เห็นว่ามีน้ำตกอื่นในทางเลือก ต่อไปนี้สอดคล้องกับตัวอย่าง OTs
when(a) {
true -> b
false -> c
}
ส่วนขยาย
เป็นตัวอย่างที่ดีหลายอย่าง ( ผู้ประกอบการเงื่อนไข Kotlin Ternary ) ในคำตอบอื่น ๆ ที่แสดงนามสกุลยังสามารถช่วยในการแก้กรณีการใช้งานของคุณ
สำหรับตัวฉันเองฉันใช้ฟังก์ชั่นส่วนขยายต่อไปนี้:
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
คนแรกจะกลับมาให้ค่าเริ่มต้นให้ในกรณีที่วัตถุเท่ากับโมฆะ ประการที่สองจะประเมินการแสดงออกที่ให้ไว้ในแลมบ์ดาในกรณีเดียวกัน
การใช้งาน:
1) e?.getMessage().or("unknown")
2) obj?.lastMessage?.timestamp.or { Date() }
ส่วนตัวฉันรหัสข้างต้นอ่านได้ง่ายกว่าการif
ก่อสร้างแบบอินไลน์
e.getMessage() ?: "unknown"
ฟังก์ชั่นแรกจะถูกแทนที่ด้วย ที่สองสามารถแสดงเป็นobj?.lastMessage?.timestamp ?: { Date() }()
Java ที่เทียบเท่ากับผู้ประกอบการที่ประกอบไปด้วยสามส่วน
a ? b : c
เป็น IF ง่ายๆใน Kotlin ในหนึ่งบรรทัด
if(a) b else c
ไม่มีผู้ประกอบการที่สาม (เงื่อนไข? แล้ว: อื่น ๆ ) เพราะธรรมดาถ้าทำงานได้ดีในบทบาทนี้
https://kotlinlang.org/docs/reference/control-flow.html#if-expression
กรณีพิเศษสำหรับการเปรียบเทียบค่า Null
คุณสามารถใช้ตัวดำเนินการ Elvis
if ( a != null ) a else b
// equivalent to
a ?: b
นอกจากนี้ยังไม่มีการดำเนินการ ternaryใน Kotlin เป็นif else
ค่าตอบแทนที่บล็อก
ดังนั้นคุณสามารถทำได้:
val max = if (a > b) a else b
แทนที่จะเป็นจาวาmax = (a > b) ? b : c
เรายังสามารถใช้การwhen
ก่อสร้างมันยังคืนค่า:
val max = when(a > b) {
true -> a
false -> b
}
นี่คือลิงค์สำหรับเอกสาร kotlin: การควบคุมการไหล: ถ้า, เมื่อ, สำหรับ, ในขณะที่
ใน Kotlin
if
คือนิพจน์คือมันส่งคืนค่า ดังนั้นจึงไม่มีผู้ประกอบการที่สาม(condition ? then : else)
เพราะปกติถ้าทำงานได้ดีในบทบาทนี้ แหล่งคู่มือจากที่นี่
// 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
บางกรณีมุมไม่ได้กล่าวถึงในคำตอบอื่น ๆ
เนื่องจากการปรากฏตัวของtakeIfในKotlin 1.1ผู้ประกอบการที่สามa ? b : c
สามารถแสดงเช่นนี้:
b.takeIf { a } ?: c
มันจะยิ่งสั้นลงในกรณีที่ c คือnull
:
b.takeIf { a }
นอกจากนี้โปรดทราบว่าโดยทั่วไปใน Java การตรวจสอบโมฆะโลกเช่นvalue != null ? value : defaultValue
แปลในอุดมคติ Kotlin เป็นเพียงvalue ?: defaultValue
เพียง
ที่คล้ายกันสามารถแปลa != null ? b : c
a?.let { b } ?: c
b.takeIf { a } ?: c
ที่สั้นกว่าและสามารถอ่านได้มากกว่าif (a) b else c
? ผู้ประกอบการ Terneray เป็นคุณลักษณะที่ขาดหายไปใน Kotlin เนื่องจากชื่อตัวแปรและเงื่อนไขอาจยาวและทำให้คุณแยกบรรทัดที่ไม่ดีออก
takeIf
จะประเมินกรณีจริงเสมอ (ที่นี่a
) ไม่เพียง แต่อาจแสดงออกคำนวณเก้อถ้าa
เกิดขึ้นจะเป็นเท็จ if (a is Int) { a + 3 }
แต่คุณไม่สามารถได้รับประโยชน์จากมันได้ปลดเปลื้องสมาร์ทลา
{ a }
เป็นแลมบ์ดาที่ประเมินอย่างเฉื่อยชา
b
) เสมอ" แต่แม้{ a }
ในขณะที่ขี้เกียจจะต้องได้รับการประเมินเพื่อกำหนดผลลัพธ์ของการแสดงออก
ดูเอกสาร :
ใน Kotlin ถ้ามีการแสดงออกคือมันจะส่งกลับค่า ดังนั้นไม่มีผู้ประกอบการที่สาม (เงื่อนไข? แล้ว: อื่น ๆ ) เพราะธรรมดาถ้าทำงานได้ดีในบทบาทนี้
ชวา
int temp = a ? b : c;
เทียบเท่ากับ Kotlin:
var temp = if (a) b else c
งาน :
ลองพิจารณาตัวอย่างต่อไปนี้:
if (!answer.isSuccessful()) {
result = "wrong"
} else {
result = answer.body().string()
}
return result
เราต้องการสิ่งที่เทียบเท่าใน Kotlin:
return (! answer.isSuccessful ())
?
"ผิด":
answer.body (). string ()
แนวทางแก้ไข :
1. ก . คุณสามารถใช้if-expression
ใน Kotlin:
return if (!answer.isSuccessful()) "wrong" else answer.body().string()
1.b มันจะดีกว่านี้มากถ้าคุณพลิกif-expression
(ทำโดยไม่ทำnot
):
return if (answer.isSuccessful()) answer.body().string() else "wrong"
2 . ผู้ดำเนินการ Elvis ของ Kotlin ?:
สามารถทำงานได้ดียิ่งขึ้น:
return answer.body()?.string() ?: "wrong"
3 . หรือใช้คลาสที่Extension function
สอดคล้องAnswer
กัน:
fun Answer.bodyOrNull(): Body? = if (isSuccessful()) body() else null
4 . การใช้รหัสExtension function
คุณสามารถลดได้ด้วยElvis operator
:
return answer.bodyOrNull()?.string() ?: "wrong"
5 . หรือเพียงแค่ใช้when
โอเปอเรเตอร์:
when (!answer.isSuccessful()) {
parseInt(str) -> result = "wrong"
else -> result = answer.body().string()
}
หวังว่านี่จะช่วยได้
เมื่อแทนที่ผู้ควบคุมสวิตช์ของภาษา C-like ในรูปแบบที่ง่ายที่สุดดูเหมือนว่านี้
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> {
print("x is neither 1 nor 2")
}
}
when
เป็นคำสั่งไม่ใช่นิพจน์ การเปรียบเทียบที่เกี่ยวข้องมากขึ้นกับนิพจน์เงื่อนไขแบบไตรภาคจะทำให้แต่ละสาขาส่งคืนค่าเช่นว่าเมื่อนิพจน์ประเมินค่า (ตามที่เกิดขึ้นกับเงื่อนไขแบบไตรภาค)
ไม่มีผู้ประกอบการที่สามใน Kotlin ดูเหมือนว่ามีปัญหาเมื่อเห็นอย่างรวดเร็วครั้งแรก แต่คิดว่าเราสามารถทำได้ด้วย inline ถ้ามีคำสั่งอื่นเพราะนี่คือการแสดงออกที่นี่ เพียงแค่เราต้องทำ -
var number = if(n>0) "Positive" else "Negetive"
ที่นี่เราสามารถทำได้ถ้าบล็อกมากเกินไปตามที่เราต้องการ ชอบ-
var number = if(n>0) "Positive" else if(n<0) "Negative" else "Zero"
ดังนั้นบรรทัดนี้จึงง่ายและอ่านได้ง่ายกว่าโอเปอร์เรเตอร์ที่ประกอบไปด้วย เมื่อเราใช้โอเปอเรเตอร์มากกว่าหนึ่งตัวในจาวาดูเหมือนว่าน่ากลัว แต่ที่นี่เรามีไวยากรณ์ที่ชัดเจน แม้ว่าเราจะสามารถเขียนเป็นหลายบรรทัดได้เช่นกัน
คุณสามารถใช้var a= if (a) b else c
แทนผู้ประกอบการที่สาม
อีกแนวคิดที่ดีของ kotlin ก็คือ Elvis operater คุณไม่จำเป็นต้องตรวจสอบค่าว่างทุกครั้ง
val l = b?.length ?: -1
นี่จะคืนค่าความยาวถ้า b ไม่เป็นโมฆะมิฉะนั้นจะเรียกใช้งานคำสั่งด้านขวา
ตามที่ Drew Noakes, kotlin ใช้ถ้าคำสั่งเป็น expression ดังนั้น Ternary Conditional Operator ไม่จำเป็นอีกต่อไป
แต่ด้วยฟังก์ชั่นส่วนขยายและการโหลดล้นคุณสามารถใช้มันด้วยตัวเองนี่คือตัวอย่าง
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
}
จากนั้นใช้แบบนี้
val grade = 90
val clazz = (grade > 80) then "A" or "B"
อีกวิธีที่น่าสนใจคือการใช้when
:
when(a) {
true -> b
false -> b
}
สามารถค่อนข้างมีประโยชน์ในบางสถานการณ์ที่ซับซ้อนมากขึ้น และจริงๆแล้วมันอ่านง่ายกว่าสำหรับฉันมากกว่าif ... else ...
คุณสามารถทำได้หลายวิธีใน Kotlin
ใช้ถ้า
if(a) b else c
ใช้เมื่อไหร่
when (a) {
true -> print("value b")
false -> print("value c")
else -> {
print("default return in any other case")
}
}
ปลอดภัยเป็นศูนย์
val a = b ?: c
ไม่มีการดำเนินงานที่สามใน Kotlin แต่มีวิธีสนุก ๆ ที่จะแก้ไข ดังที่คนอื่น ๆ ชี้ให้เห็นการแปลโดยตรงไปยัง Kotlin จะมีลักษณะเช่นนี้:
val x = if (condition) result1 else result2
แต่โดยส่วนตัวแล้วฉันคิดว่ามันอาจจะรกไปหน่อยและอ่านยาก มีตัวเลือกอื่น ๆ ในห้องสมุด คุณสามารถใช้ takeIf {} กับตัวดำเนินการ elvis:
val x = result1.takeIf { condition } ?: result2
สิ่งที่เกิดขึ้นนั่นคือคำสั่ง takeIf {} ส่งคืนผลลัพธ์ของคุณ 1 หรือ null และตัวดำเนินการ elvis จัดการตัวเลือก null มีตัวเลือกเพิ่มเติมตัวอย่างเช่น TakeUnless {}:
val x = result1.takeUnless { condition } ?: result2
ภาษาชัดเจนคุณรู้ว่ากำลังทำอะไร
หากเป็นเงื่อนไขที่ใช้กันโดยทั่วไปคุณสามารถทำสิ่งสนุก ๆ เช่นใช้วิธีการขยายแบบอินไลน์ สมมติว่าเราต้องการติดตามคะแนนเกมเป็น Int และเราต้องการส่งกลับ 0 เสมอหากเงื่อนไขไม่ได้รับ:
inline fun Int.zeroIfFalse(func: () -> Boolean) : Int = if (!func.invoke()) 0 else this
ตกลงว่าน่าเกลียด แต่ให้พิจารณาว่ามันมีลักษณะอย่างไรเมื่อใช้งาน:
var score = 0
val twoPointer = 2
val threePointer = 3
score += twoPointer.zeroIfFalse { scoreCondition }
score += threePointer.zeroIfFalse { scoreCondition }
อย่างที่คุณเห็น Kotlin มีความยืดหยุ่นอย่างมากในการเลือกรหัสของคุณ มีตัวอย่างมากมายของฉันและอาจเป็นไปได้ว่าฉันยังไม่ได้ค้นพบ ฉันหวังว่านี่จะช่วยได้!
takeIf
เป็นตัวเลือกที่ชื่นชอบแน่นอนหรูหรามาก
จำผู้ประกอบการ Ternaryและผู้ดำเนินการElvisแยกความหมายในKotlinซึ่งแตกต่างจากภาษายอดนิยมจำนวนมาก การทำexpression? value1: value2
จะให้คุณคำพูดที่ไม่ดีโดยKotlinคอมไพเลอร์ซึ่งแตกต่างจากภาษาอื่น ๆ ที่มีอยู่ไม่มีผู้ประกอบ ternary ใน Kotlinเป็นที่กล่าวถึงในเอกสารอย่างเป็นทางการ เหตุผลก็คือประโยคif, when and try-catch จะส่งคืนค่าเอง
ดังนั้นการทำexpression? value1: value2
สามารถถูกแทนที่ด้วย
val max = ถ้า (a> b) พิมพ์ ("เลือก a") พิมพ์อื่น ("เลือก b")
ผู้ประกอบการเอลวิสที่Kotlinได้ทำงานเฉพาะในกรณีของตัวแปร nullable อดีต .:
ถ้าผมทำสิ่งที่ชอบ
value3 = value1 ?: value2
แล้วถ้าvalue1เป็นโมฆะแล้วvalue2จะกลับมิฉะนั้นค่า 1จะถูกส่งกลับ
คุณสามารถใช้if
นิพจน์สำหรับสิ่งนี้ได้ใน Kotlin ใน Kotlin if
คือนิพจน์ที่มีค่าผลลัพธ์ ดังนั้นใน Kotlin เราสามารถเขียนได้
fun max(a: Int, b: Int) = if (a > b) a else b
และใน Java เราสามารถบรรลุเหมือนกัน แต่ด้วยรหัสขนาดใหญ่
int max(int a, int b) {
return a > b ? a : b
}
หากคุณไม่ได้ใช้สัญกรณ์มาตรฐานคุณสามารถสร้าง / จำลองโดยใช้infixกับสิ่งนี้:
สร้างคลาสเพื่อเก็บเป้าหมายและผลลัพธ์ของคุณ:
data class Ternary<T>(val target: T, val result: Boolean)
สร้างฟังก์ชั่น infix เพื่อจำลองการทำงานแบบไตรภาค
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
}
จากนั้นคุณจะสามารถใช้มันได้เช่นนี้:
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"
อีกแนวทางสั้น ๆ ในการใช้งาน
val value : String = "Kotlin"
value ?: ""
ที่นี่ kotlin ตรวจสอบตัวเองเป็นโมฆะและถ้าเป็นโมฆะ
ทำไมคนเราจะใช้สิ่งนี้:
when(a) {
true -> b
false -> b
}
เมื่อคุณสามารถใช้บางสิ่งเช่นนี้ ( a
เป็นบูลีนในกรณีนี้):
when {
a -> b
else -> b
}
? and :
ขัดแย้งกับการประกาศเป็นโมฆะ / ประเภทมากกว่าการตรวจสอบประเภท นอกเหนือจากนั้นฉันไม่เห็นเหตุผลใด ๆ ฉันคิดว่าบางคนจะใส่ความคิดบางอย่างแน่นอนถ้ามีการตรวจสอบแบบอินไลน์ถ้า - อื่นเงื่อนไข มาดูกันในรุ่นอนาคตกันดีกว่า
เมื่อทำงานกับการใช้ () ให้ดูเหมือนว่ามีประโยชน์มากเมื่อจัดการกับการดำเนินการแบบไตรภาคเนื่องจากมันมีความหรูหราและให้ห้องคุณ
val columns: List<String> = ...
val band = Band().apply {
name = columns[0]
album = columns[1]
year = columns[2].takeIf { it.isNotEmpty() }?.let { it.toInt() } ?: 0
}
ด้วยฟังก์ชั่น infix ต่อไปนี้ฉันสามารถครอบคลุมกรณีการใช้งานทั่วไปได้หลายอย่างในแบบเดียวกับที่มันสามารถทำได้ใน 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
ไม่มีผู้ประกอบการที่สามใน Kotlin ที่ปิดมากที่สุดคือด้านล่างทั้งสองกรณี
val a = true if(a) print("A is true") else print("A is false")
หากนิพจน์ทางด้านซ้ายของ?: ไม่ใช่โมฆะตัวดำเนินการ elvis จะส่งกลับมิฉะนั้นจะส่งคืนนิพจน์ทางด้านขวา โปรดทราบว่านิพจน์ทางด้านขวาจะได้รับการประเมินเฉพาะในกรณีที่ด้านซ้ายเป็นโมฆะ
val name = node.getName() ?: throw IllegalArgumentException("name expected")
ตัวอย่าง: var energy: Int = data? .get (position) ?. energy? .toInt ()?: 0
ใน kotlin ถ้าคุณใช้ ?: มันจะทำงานอย่างไรถ้าคำสั่งจะคืนค่า null แล้ว ?: 0มันจะใช้ 0 หรืออะไรก็ตามที่คุณเขียนด้านนี้
ใน Kotlin คุณสามารถใช้การดำเนินการแบบไตรภาคเช่นนี้: val x = if(a) "add b" else "add c"
หลังจากการวิจัยความคิดอื่น ๆ ฉันได้รับผู้ประกอบการที่ประกอบไปด้วย:
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
ตัวอย่าง (เรียกใช้ที่นี่ ):
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")
}
}
รุ่นนี้คล่องแคล่วและไม่ขัดแย้งกับตัวดำเนินการรวมศูนย์ว่าง
then
yes