รวดเร็วถ้าให้คำสั่งใน Kotlin


123

ใน Kotlin มีเทียบเท่ากับรหัส Swift ด้านล่างหรือไม่?

if let a = b.val {

}
else {

}

คำตอบ:


255

คุณสามารถใช้letฟังก์ชันนี้:

val a = b?.let {
    // If b is not null.
} ?: run {
    // If b is null.
}

โปรดทราบว่าคุณต้องเรียกใช้runฟังก์ชันเฉพาะเมื่อคุณต้องการบล็อกโค้ดเท่านั้น คุณสามารถลบrun-block ออกได้หากคุณมี oneliner หลัง elvis-operator ( ?:) เท่านั้น

ทราบว่าrunบล็อกจะมีการประเมินทั้งหากbเป็นโมฆะหรือหากletประเมิน -block nullไป

ด้วยเหตุนี้คุณจึงต้องการเพียงแค่การifแสดงออก

val a = if (b == null) {
    // ...
} else {
    // ...
}

ในกรณีนี้else-block จะได้รับการประเมินbก็ต่อเมื่อไม่เป็นโมฆะ


42
มันไม่เทียบเท่า aไม่สามารถเข้าถึงภายในletและrunปิดกั้นได้
Jacky Choi

6
aยังไม่ได้กำหนดไว้ในขอบเขตletและrun. แต่คุณสามารถเข้าถึงค่าของbภายในที่มีพารามิเตอร์โดยปริยายlet itสิ่งนี้มีจุดประสงค์เดียวกับที่ฉันเดา
marstran

1
รหัสที่รวดเร็วจะเสร็จสิ้นการมอบหมายaก่อนบล็อกโค้ดเหล่านั้น และaสามารถเข้าถึงได้ภายใน.
Jacky Choi

1
มันมอบหมายให้aอะไร? ถ้าเป็นbเช่นนั้นก็itมีจุดประสงค์เดียวกัน มันกำหนดใหม่aด้วยผลลัพธ์ของval-block หรือไม่?
marstran

3
คุณสามารถเข้าถึงได้itจากในletบล็อกเท่านั้น ผลของletหรือบล็อกจะได้รับมอบหมายให้run aผลลัพธ์คือนิพจน์สุดท้ายในบล็อก คุณใช้การมอบหมายหลังจาก let / runเสร็จสิ้นเช่นเดียวกับที่คุณทำกับงานอื่น ๆ ตามปกติ
marstran

52

ก่อนอื่นให้แน่ใจว่าเราเข้าใจความหมายของสำนวน Swift ที่ให้มา:

if let a = <expr> {
     // then-block
}
else {
     // else-block
}

ซึ่งหมายความว่า: "ถ้า<expr>ผลลัพธ์เป็น non-nil ทางเลือกให้ป้อนthen-block ที่มีสัญลักษณ์aผูกไว้กับค่าที่ไม่ได้elseปิดกั้นมิฉะนั้นให้ป้อนบล็อก

โดยเฉพาะอย่างยิ่งโปรดทราบว่าaถูกผูกไว้ภายในthen-blockเท่านั้น ใน Kotlin คุณสามารถรับสิ่งนี้ได้อย่างง่ายดายโดยโทร

<expr>?.also { a ->
    // then-block
}

และคุณสามารถเพิ่มelse-block ดังนี้:

<expr>?.also { a ->
    // then-block
} ?: run {
    // else-block
}

ส่งผลให้มีความหมายเช่นเดียวกับสำนวน Swift


11

คำตอบของฉันคือแมวคัดลอกจากตัวอื่น ๆ ทั้งหมด อย่างไรก็ตามฉันไม่สามารถเข้าใจการแสดงออกของพวกเขาได้อย่างง่ายดาย ดังนั้นฉันเดาว่ามันจะเป็นการดีที่จะให้คำตอบที่เข้าใจได้มากขึ้น

อย่างรวดเร็ว:

if let a = b.val {
  //use "a" as unwrapped
}
else {

}

ใน Kotlin:

b.val?.let{a -> 
  //use "a" as unwrapped
} ?: run{
  //else case
}

การใช้letแทนalsoวิธีที่runบล็อกจะดำเนินการเมื่อใดก็ตามที่letบล็อกกลับnullมาซึ่งไม่ใช่สิ่งที่เราต้องการ
Marko Topolnik

6

ไม่เหมือน Swift ตรงที่ไม่จำเป็นต้องแกะอุปกรณ์เสริมก่อนใช้ใน Kotlin เราสามารถตรวจสอบได้ว่าค่านั้นไม่เป็นโมฆะหรือไม่และคอมไพลเลอร์ติดตามข้อมูลเกี่ยวกับการตรวจสอบที่คุณดำเนินการและอนุญาตให้ใช้โดยไม่ได้ปิดกั้น

ใน Swift:

if let a = b.val {
  //use "a" as unwrapped
} else {

}

ใน Kotlin:

if b.val != null {
  //use "b.val" as unwrapped
} else {

}

อ้างอิงเอกสาร: (null-safety)สำหรับกรณีการใช้งานเพิ่มเติมดังกล่าว


สิ่งนี้ใช้ได้เฉพาะเมื่อ b เป็นตัวแปรภายในเครื่อง แล้วตัวแปรคลาสล่ะ?
Warpzit

5

if let คำให้การ.

Swift's Optional Binding( if-letคำสั่งที่เรียกว่า) ใช้เพื่อค้นหาว่าตัวเลือกมีค่าหรือไม่และถ้าเป็นเช่นนั้นเพื่อให้ค่านั้นพร้อมใช้งานเป็นค่าคงที่ชั่วคราวหรือตัวแปร ดังนั้นOptional Bindingสำหรับif-letคำสั่งมีดังนี้:

if-letคำสั่งของ Swift :

let b: Int? = 50

if let a = b {
    print("Good news!")
} else {
    print("Equal to 'nil' or not set")
}

/*  RESULT: Good news!  */

ใน Kotlin เช่นเดียวกับใน Swift เพื่อหลีกเลี่ยงข้อขัดข้องที่เกิดจากการพยายามเข้าถึงค่า null เมื่อไม่ได้คาดไว้จะมีการจัดเตรียมไวยากรณ์เฉพาะ (เช่นb.let { }ในตัวอย่างที่สอง) ไว้สำหรับการคลายการตัดอย่างถูกต้องnullable types:

Kotlin เทียบเท่า 1ในif-letคำสั่งของ Swift :

val b: Int? = null
val a = b

if (a != null) { 
    println("Good news!")
} else { 
    println("Equal to 'null' or not set")
}

/*  RESULT: Equal to 'null' or not set  */

letฟังก์ชันของ Kotlin เมื่อใช้ร่วมกับตัวดำเนินการโทรปลอดภัย?:จะให้วิธีที่กระชับในการจัดการนิพจน์ที่เป็นโมฆะ

Kotlin เทียบเท่า 2 (ฟังก์ชัน Inline let และ Elvis Operator)ของif-letคำสั่งของ Swift :

val b: Int? = null

val a = b.let { nonNullable -> nonNullable } ?: "Equal to 'null' or not set"
println(a)

/*  RESULT: Equal to 'null' or not set  */

ใส่คำอธิบายภาพที่นี่

guard let คำให้การ.

guard-letคำสั่งใน Swift นั้นเรียบง่ายและทรงพลัง ตรวจสอบเงื่อนไขบางอย่างและหากประเมินว่าเป็นเท็จelseคำสั่งจะดำเนินการซึ่งโดยปกติจะออกจากเมธอด

ลองสำรวจguard-letคำสั่งของ Swift :

let b: Int? = nil

func testIt() {
    guard let a = b else {
        print("Equal to 'nil' or not set")
        return
    }
    print("Good news!")
}
testIt()

/*  RESULT: Equal to 'nil' or not set  */

ผลที่คล้ายกันของ Kotlinจากguard-letคำสั่งของ Swift :

ไม่เหมือน Swift ใน Kotlin ไม่มีคำสั่งยามเลย อย่างไรก็ตามคุณสามารถใช้Elvis Operator- ?:เพื่อให้ได้เอฟเฟกต์ที่คล้ายกัน

val b: Int? = 50

fun testIt() {
    val a = b ?: return println("Equal to 'null' or not set")
    return println("Good news!")
}
testIt()

/*  RESULT: Good news!  */

หวังว่านี่จะช่วยได้


4

นี่คือวิธีรันโค้ดเฉพาะเมื่อnameไม่เป็นโมฆะ:

var name: String? = null
name?.let { nameUnwrapp ->
    println(nameUnwrapp)  // not printed because name was null
}
name = "Alex"
name?.let { nameUnwrapp ->
    println(nameUnwrapp)  // printed "Alex"
}

ถ้า name == โค้ด null ใน {} ไม่รันถ้า name เป็น String - code execute: nameUnwrapp == name
АлександрЯковенко

1
ผมไม่คิดว่านี่คือสิ่งที่ OP จะขอให้ผมมั่นใจว่า OP รู้อยู่แล้วว่าสิ่งที่letไม่ แต่คำถามคือเกี่ยวกับelseกลยุทธ์ที่รันถ้าวัตถุที่ถูกเรียกว่าเป็นlet nullSwift มีวิธีที่เป็นธรรมชาติมากขึ้น (โต้แย้งได้) แต่หลังจากทำทั้ง Kotlin และ Swift เป็นจำนวนมากฉันหวังว่า Kotlin จะมีการแกะแบบง่ายๆเหมือนที่ Swift ทำ
kalehv

2

นี่คือตัวแปรของฉัน จำกัด เฉพาะกรณี "if not null" ที่พบบ่อย

ก่อนอื่นกำหนดสิ่งนี้ไว้ที่ใดที่หนึ่ง:

inline fun <T> ifNotNull(obj: T?, block: (T) -> Unit) {
    if (obj != null) {
        block(obj)
    }
}

มันอาจจะinternalเพื่อหลีกเลี่ยงความขัดแย้ง

ตอนนี้แปลงรหัส Swift นี้:

if let item = obj.item {
    doSomething(item)
}

สำหรับรหัส Kotlin นี้:

ifNotNull(obj.item) { item -> 
    doSomething(item)
}

โปรดทราบว่าเช่นเคยกับบล็อกใน Kotlin คุณสามารถวางอาร์กิวเมนต์และใช้it:

ifNotNull(obj.item) {
    doSomething(it)
}

แต่ถ้าบล็อกมีมากกว่า 1-2 บรรทัดก็น่าจะดีที่สุด

สิ่งนี้คล้ายกับ Swift เท่าที่ฉันจะหาได้


0

มีวิธีที่คล้ายกันใน kotlin เพื่อให้ได้รูปแบบ if-let ของ Swift

if (val a = b) {
    a.doFirst()
    a.doSecond()
}

คุณยังสามารถกำหนดค่าที่เป็นโมฆะได้หลายค่า

if (val name = nullableName, val age = nullableAge) {
    doSomething(name, age)
}

แนวทางแบบนี้จะเหมาะสมกว่าหากใช้ค่าที่เป็นโมฆะได้มากกว่า 1 ครั้ง ในความคิดของฉันมันช่วยในด้านประสิทธิภาพเนื่องจากค่าที่เป็นโมฆะจะถูกตรวจสอบเพียงครั้งเดียว

ที่มา: Kotlin Discussion


1
โปรดทราบว่าแนวทางที่คุณแสดงไม่ได้รวบรวมไว้ในขณะนี้ เป็นเพียงคำแนะนำในการปรับเปลี่ยนภาษา Kotlin เพื่อจัดการกับปัญหานี้ ดังนั้นนี่ไม่ใช่วิธีแก้ปัญหาที่ถูกต้อง
Peter F

0

ฉันกำลังเพิ่มคำตอบนี้เพื่อชี้แจงคำตอบที่ยอมรับเนื่องจากมันใหญ่เกินไปสำหรับความคิดเห็น

รูปแบบทั่วไปที่นี่คือคุณสามารถใช้การรวมกันของฟังก์ชันขอบเขตที่มีอยู่ใน Kotlin โดยคั่นด้วยตัวดำเนินการเอลวิสดังนี้:

<nullable>?.<scope function> {
    // code if not null
} :? <scope function> {
    // code if null
}

ตัวอย่างเช่น:

val gradedStudent = student?.apply {
    grade = newGrade
} :? with(newGrade) {
    Student().apply { grade = newGrade }
}

-1

ตัวเลือกที่สะอาดที่สุดในความคิดของฉันคือนี่

สวิฟท์:

if let a = b.val {

} else {

}

Kotlin

b.val.also { a ->

} ?: run {

}

-1

รวดเร็วถ้าให้คำสั่งใน Kotlin

คำตอบสั้น ๆ คือใช้IF-ELSEอย่างง่ายตามเวลาของความคิดเห็นนี้ไม่มีสิ่งที่เทียบเท่าใน Kotlin LET

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