อะไร: ทำใน Kotlin? (ผู้ดำเนินการเอลวิส)


98

ฉันคิดไม่ออกว่า?:จะทำอย่างไรในกรณีนี้

val list = mutableList ?: mutableListOf() 

และเหตุใดจึงสามารถแก้ไขได้

val list = if (mutableList != null) mutableList else mutableListOf()

5
กลับด้านซ้ายหากไม่เป็นโมฆะมิฉะนั้นกลับด้านขวา นิพจน์แรกคือสัญกรณ์สั้น ๆ สำหรับนิพจน์ที่สอง kotlinlang.org/docs/reference/null-safety.html#elvis-operator
Eugen Pechanec

คำตอบ:


115

TL; DR: หากการอ้างอิงอ็อบเจ็กต์ผลลัพธ์ [ตัวถูกดำเนินการตัวแรก] ไม่nullถูกส่งคืน มิฉะนั้นค่าของตัวถูกดำเนินการที่สอง (ซึ่งอาจเป็นnull) จะถูกส่งกลับ


ตัวดำเนินการ Elvisเป็นส่วนหนึ่งของภาษาโปรแกรมหลายภาษาเช่น Kotlin แต่ยังรวมถึง Groovy หรือ C # ฉันพบว่าคำจำกัดความของWikipediaค่อนข้างแม่นยำ:

ในภาษาโปรแกรมคอมพิวเตอร์บางภาษาตัวดำเนินการ Elvis ?:เป็นตัวดำเนินการไบนารีที่ส่งคืนตัวถูกดำเนินการตัวแรกหากตัวถูกดำเนินการนั้นเป็นtrueและจะประเมินและส่งคืนตัวถูกดำเนินการตัวที่สอง มันเป็นความแตกต่างจากผู้ประกอบการที่มีเงื่อนไข ternary , ? :พบในภาษาเหล่านั้น (และอื่น ๆ อีกมากมาย): ผู้ประกอบการเอลวิสเป็นผู้ประกอบ ternary กับตัวถูกดำเนินการที่สองของการละเว้น

สิ่งต่อไปนี้เป็นจริงโดยเฉพาะอย่างยิ่งสำหรับ Kotlin:

ภาษาโปรแกรมคอมพิวเตอร์บางภาษามีความหมายที่แตกต่างกันสำหรับตัวดำเนินการนี้ แทนการถูกดำเนินการครั้งแรกที่มีการผลในแบบบูลนั้นจะต้องส่งผลในการอ้างอิงวัตถุ หากการอ้างอิงอ็อบเจ็กต์ผลลัพธ์ไม่nullได้รับการส่งคืน มิฉะนั้นค่าของตัวถูกดำเนินการที่สอง (ซึ่งอาจเป็นnull) จะถูกส่งกลับ

ตัวอย่าง:

x ?: y // yields `x` if `x` is not null, `y` otherwise.

3
นี่มันเจ๋งมาก ฉันไม่เคยคิดว่าelvis operatorจะลดลงเป็นอย่างอื่นได้อีก ดี! และคำอธิบายที่ดีขอบคุณ!
sud007

88

ตัวดำเนินการเอลวิสแสดงด้วยเครื่องหมายคำถามตามด้วยเครื่องหมายจุดคู่: ?:และสามารถใช้กับไวยากรณ์นี้ได้:

first operand ?: second operand

ช่วยให้คุณสามารถเขียนรหัสที่ปลอดภัยและทำงานได้ดังนี้:

หากfirst operand ไม่เป็นค่าว่างระบบจะส่งคืน หากเป็นค่าว่างระบบsecond operandจะส่งคืน สามารถใช้เพื่อรับประกันว่านิพจน์จะไม่คืนค่าว่างเนื่องจากคุณจะระบุค่าที่ไม่เป็นค่าว่างได้หากค่าที่ระบุเป็นค่าว่าง


ตัวอย่างเช่น (ใน Kotlin):

fun retrieveString(): String {    //Notice that this type isn't nullable
    val nullableVariable: String? = getPotentialNull() //This variable may be null
    
    return nullableVariable ?: "Secondary Not-Null String"
}

ในกรณีนี้หากค่าที่คำนวณgetPotentialNullไม่ได้เป็นค่าว่างจะถูกส่งกลับโดยretrieveString; ถ้าเป็นโมฆะนิพจน์ที่สอง"Secondary Not-Null String"จะถูกส่งกลับแทน

นอกจากนี้โปรดทราบว่านิพจน์ด้านขวามือจะได้รับการประเมินก็ต่อเมื่อด้านซ้ายมือเป็นค่าว่างโมฆะ

ใน Kotlin คุณสามารถใช้นิพจน์ใดก็ได้second operandเช่นthrow Exceptionนิพจน์

return nullVariable ?: throw IllegalResponseException("My inner function returned null! Oh no!")

ชื่อผู้ประกอบการเอลวิสมาจากการที่มีชื่อเสียงนักร้องชาวอเมริกันเอลวิสเพรสลีย์ ทรงผมของเขาคล้ายกับเครื่องหมายคำถาม

เครื่องหมายคำถามเอลวิส

ที่มา: Wojda, I. Moskala, M. การพัฒนา Android ด้วย Kotlin 2560. Packt Publishing


84
บวก 1 สำหรับการแสดง Mr Presley
s1m0nw1

7
? :) (ดูเป็นเอลวิสยิ้ม)
LeoColman

1
หลังจากนั้นไม่นานฉันไม่เข้าใจว่าทำไมจึงเรียกว่า Elvis Operator ภาพประกอบของคุณทำให้ฉันรู้ว่าทำไมมันถึงเรียกว่า Elvis Operator :)
Yohanes AI

เรื่องราวเกี่ยวกับเอลวิสเป็นเรื่องจริงหรือไม่? haha
Hillcow

@Kerooker เขาไม่ยิ้ม,?: | จะดีกว่า IMO
ahmed galal

38

สิ่งนี้เรียกว่าตัวดำเนินการเอลวิสและทำ ... ตรงกับที่คุณอธิบายไว้ในคำถามของคุณ หากด้านซ้ายมือเป็นnullค่าจะส่งกลับด้านขวาแทนโดยจัดเรียงเป็นทางเลือก มิฉะนั้นจะส่งกลับค่าทางด้านซ้ายมือ

a ?: bif (a != null) a else bเป็นเพียงการจดชวเลข

ตัวอย่างเพิ่มเติมพร้อมประเภท:

val x: String? = "foo"
val y: String = x ?: "bar"      // "foo", because x was non-null    

val a: String? = null
val b: String = a ?: "bar"      // "bar", because a was null

10
ถ้าคุณมาจาก java มันเป็นชวเลขมากกว่าสำหรับ:a != null ? a : b
crgarridos

9

ลองมาดูคำจำกัดความ :

เมื่อเรามีการอ้างอิงที่เป็นโมฆะเราสามารถพูดได้ว่า "ถ้า r ไม่ใช่ค่าว่างให้ใช้หรือใช้ค่าที่ไม่ใช่ค่าว่าง x":

?: (Elvis) หลีกเลี่ยงการใช้คำฟุ่มเฟือยและทำให้โค้ดของคุณกระชับ

ตัวอย่างเช่นฟังก์ชันส่วนขยายคอลเล็กชันจำนวนมากจะคืนค่าnullเป็นทางเลือก

listOf(1, 2, 3).firstOrNull { it == 4 } ?: throw IllegalStateException("Ups")

?:ช่วยให้คุณสามารถจัดการกับกรณีสำรองได้อย่างดีเยี่ยมแม้ว่าคุณจะมีทางเลือกหลายชั้น ในกรณีนี้คุณสามารถเชื่อมโยงตัวดำเนินการ Elvis แบบทวีคูณได้ดังนี้:

val l = listOf(1, 2, 3)

val x = l.firstOrNull { it == 4 } ?: l.firstOrNull { it == 5 } ?: throw IllegalStateException("Ups")

หากคุณจะแสดงสิ่งเดียวกันกับ if else รหัสจะเป็นจำนวนมากซึ่งอ่านยากกว่า


3

เราสามารถพูดได้ว่าคุณมีสองมือ อยากทราบว่าตอนนี้มือซ้ายของคุณใช้งานได้หรือไม่. ถ้ามือซ้ายไม่ทำงานreturn emptyอย่างอื่นbusy

ตัวอย่างสำหรับ Java:

private int a;
if(a != null){
    println("a is not null, Value is: "+a)
}
else{
    println("a is null")
}

ตัวอย่างสำหรับ Kotlin:

val a : Int = 5
val l : Int = if (a != null) a.length else "a is null"

รักคำตอบนี้ สะอาดมากเกินไปที่จะเข้าใจ
Gk Mohammad Emon

2

โดยทั่วไปหากด้านซ้ายของ Elvis ส่งคืนค่าว่างด้วยเหตุผลบางประการให้ส่งกลับด้านขวาแทน

กล่าวคือ

val number: Int? = null
println(number ?: "Number is null")

ดังนั้นหากตัวเลขไม่เป็นค่าว่างระบบจะพิมพ์หมายเลขมิฉะนั้นจะพิมพ์ "Number is null"


1

ตัวดำเนินการ elvis ใน Kotlin ใช้เพื่อความปลอดภัยที่เป็นโมฆะ

x = a ?: b

ในโค้ดข้างต้นxจะถูกกำหนดค่าของaถ้าไม่ได้nullและbถ้าเป็นanull

รหัส kotlin ที่เทียบเท่าโดยไม่ใช้ตัวดำเนินการ elvis อยู่ด้านล่าง:

x = if(a == null) b else a

1

เพิ่มเติมเล็กน้อยแม้ว่านี่คือ

X = A ?: B

Xจะยังคงเป็นnullถ้าทั้งสองอย่างAและBประเมินเป็นnull

ดังนั้นหากคุณต้องการXเป็นเสมอnon-nullตรวจสอบให้แน่ใจว่าBa non-nullหรือที่Bประเมินเสมอnon-nullว่าเป็นฟังก์ชันหรือนิพจน์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.