斯威夫特如果在科特林发表声明

ior*_*i24 104 kotlin

在Kotlin中有一个等同于下面的Swift代码吗?

if let a = b.val {

}
else {

}
Run Code Online (Sandbox Code Playgroud)

mar*_*ran 217

你可以let像这样使用-function:

val a = b?.let {
    // If b is not null.
} ?: run {
    // If b is null.
}
Run Code Online (Sandbox Code Playgroud)

请注意,run只有在需要代码块时才需要调用该函数.run如果在elvis-operator(?:)之后只有一个oneliner,则可以删除-block .

请注意,run如果b为null,或者let-block求值为,则将对该块进行求值null.

因此,您通常只需要一个if表达式.

val a = if (b == null) {
    // ...
} else {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,else只有在bnull时才会评估-block .

  • 它不等同.在`let`和`run`块中无法访问`a`. (35认同)
  • 在`let`和`run`的范围内尚未定义`a`.但是您可以使用隐式参数`it`访问`let`中的`b`的值.这符合我的想法. (5认同)
  • 你只能从`let`块中访问`it`.`let`或`run`块的结果将分配给`a`.结果是块中的最后一个表达式.您使用赋值_after_`let` /`run`已完成,就像您使用任何其他正常赋值一样. (3认同)
  • 这种成语到成语的翻译其实是错误的。Swift 代码不会导致符号“a”在“if let”表达式之后定义,它只是为“if let”的“then”子句定义的。 (2认同)
  • 应该使用 `also` 而不是 `let` 或 `run` 将在 `let` 返回 null 时执行:`b?.let { null } ?: run { /* will always execute */ }` (2认同)
  • if let 存在的原因正是它提供的范围控制。它允许您捕获可选类型表达式的结果,而无需将其导出到函数体的其余部分。这就是为什么像 `b?.let ...` 这样的例子没有展示它的目的:如果你的代码中有这个,你也可以写 `if (b != null) { ... } ` 在 Swift 中,如果你有 `if let b { ... }`,你也可以有 `if b != nil { ... }` 没有语言会为此引入特殊语法。 (2认同)

Mar*_*nik 38

让我们首先确保我们理解所提供的Swift习语的语义:

if let a = <expr> {
     // then-block
}
else {
     // else-block
}
Run Code Online (Sandbox Code Playgroud)

这意味着:"如果<expr>结果为非零可选,则输入then带有符号a绑定到未包装值的-block.否则输入else块.

特别注意,它只在-block中a绑定.在Kotlin,您可以通过致电轻松获得此信息then

<expr>?.also { a ->
    // then-block
}
Run Code Online (Sandbox Code Playgroud)

你可以else像这样添加一个-block:

<expr>?.also { a ->
    // then-block
} ?: run {
    // else-block
}
Run Code Online (Sandbox Code Playgroud)

这导致与Swift习语相同的语义.但是,如果您希望将整个习语视为表达式并检索其结果,则仍然存在差异,因此在Swift中:

if let a = <expr> {
     // then-block
}
else {
     // else-block
}
Run Code Online (Sandbox Code Playgroud)

如果<expr>是非可选类型,那么你可以使用这个成语:

<expr>?.also { a ->
    // then-block
}
Run Code Online (Sandbox Code Playgroud)

它以间接方式工作:我们正在计算一个非空值,因此then评估a意味着else评估为a.

对于适用于可空结果的完全一般情况,我找不到在Kotlin中表达这种情况的自然方式,而不会泄漏thenelse-block 之外的范围.

  • 这应该是公认的答案。 (3认同)
  • `also` 是与 `if let` 最接近的匹配,谢谢。 (3认同)
  • 很好的答案,正如 @Leon 所说,这是最接近 Swift 的“if let”。感谢您的解释 - 这应该是公认的答案。应该使用 `also` 而不是 `let`,因为 Kotlin `let` 返回一个值...谢谢! (2认同)
  • 我们不能将其更改为可接受的答案吗?在这种情况下,“也”比“让”更好 (2认同)

Sea*_*ean 14

上面有两个答案,都得到了很多接受:

  1. 斯特?{ } ?: 运行 { }
  2. 斯特?{ } ?: 运行 { }

两者似乎都适用于大多数用法,但#1 在以下测试中会失败:

在此输入图像描述

#2 似乎更好。

  • 这是正确答案!不要使用变量?.let { doStuff() } ?: run { doOtherStuff() } 因为 doStuff 返回 null 那么 run 块也会运行。还将返回传递给 lambda 的值,因此如果存在空值,它将始终返回一个值。 (2认同)

ARG*_*Geo 9

if let 陈述。

Swift 的Optional Binding(所谓的if-let语句)用于确定一个可选项是否包含一个值,如果是,则将该值作为临时常量或变量可用。所以,一个Optional Bindingforif-let语句如下:

斯威夫特的if-let声明:

let b: Int? = 50

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

/*  RESULT: Good news!  */
Run Code Online (Sandbox Code Playgroud)

在 Kotlin 中,就像在 Swift 中一样,为了避免在不期望的情况下尝试访问 null 值而导致崩溃,提供了特定的语法(如b.let { }第二个示例中所示)以正确解包nullable types

Kotlin 相当于Swiftif-let声明的 1:

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  */
Run Code Online (Sandbox Code Playgroud)

Kotlin 的let函数与安全调用运算符 结合使用时?:,提供了一种处理可为空表达式的简洁方法。

Swift语句的Kotlin 等效 2 (内联 let 函数和 Elvis 运算符)if-let

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  */
Run Code Online (Sandbox Code Playgroud)


guard let 陈述。

guard-letSwift 中的语句简单而强大。它检查某些条件,如果评估结果为假,则else执行该语句,通常会退出一个方法。

让我们来看看 Swift 的guard-let语句:

let b: Int? = nil

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

/*  RESULT: Equal to 'nil' or not set  */
Run Code Online (Sandbox Code Playgroud)

Kotlin 的类似Swiftguard-let语句的效果

与 Swift 不同的是,在 Kotlin 中,根本没有保护语句。但是,您可以使用Elvis Operator?:来获得类似的效果。

val b: Int? = 50

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

/*  RESULT: Good news!  */
Run Code Online (Sandbox Code Playgroud)


小智 7

我的回答完全是别人的模仿。但是,我不容易理解它们的表达。因此,我想提供一个更容易理解的答案会很好。

迅速地:

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

}
Run Code Online (Sandbox Code Playgroud)

在科特林:

b.val?.let{a -> 
  //use "a" as unwrapped
} ?: run{
  //else case
}
Run Code Online (Sandbox Code Playgroud)

  • 使用“let”而不是“also”意味着只要“let”块返回“null”,“run”块就会执行,这不是我们想要的。 (5认同)

Sha*_* KS 7

与 Swift 不同的是,在 Kotlin 中使用它之前不需要解开可选项。我们可以只检查该值是否为非空,编译器会跟踪有关您执行的检查的信息,并允许将其用作未包装的。

在斯威夫特:

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

}
Run Code Online (Sandbox Code Playgroud)

在科特林:

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

}
Run Code Online (Sandbox Code Playgroud)

有关更多此类用例,请参阅文档:(空安全)

  • 仅当 b 是局部变量时才有效。那么类变量呢? (3认同)

小智 5

以下是仅在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"
}
Run Code Online (Sandbox Code Playgroud)

  • 我不认为这就是OP所问的,我确信OP已经知道`let`做了什么,但问题是关于如果调用`let`的对象是`null`时执行的`else`策略。Swift 以更自然(有争议)的方式实现它。但在对 Kotlin 和 Swift 都做了很多工作之后,我确实希望 Kotlin 能够像 Swift 一样进行简单的解包。 (2认同)