简体   繁体   English

在函数中声明 val 而不初始化

[英]Declare val without initialization in function

class Solution { 
    val message: String  //error : val must be initialized or abstract
    message = "love" //error : val cannot be reassigned
}

I understand what's happening in here - val cannot be reassigned.我明白这里发生了什么 - val 不能重新分配。
So when I need val but can not initialize it i used to use by lazy因此,当我需要 val 但无法初始化它时,我曾使用by lazy

class Solution {
    fun love(){
        val message : String
        message = "love"   //this works
        message = "hate"   //this is error "val cannot be reassigned"
    }
}

Here I can delcare val without initialization and later write code message = "love" .what's happening here?在这里,我可以在不初始化的情况下 delcare val,然后编写代码message = "love" 。这里发生了什么?

@deHaar noticed correctly that only var (mutable variable) is appropriate in your case. @deHaar正确地注意到只有var (可变变量)适合您的情况。

The error you get is absolutely correct and expected.你得到的错误是绝对正确和预期的。

what's happening here?这里发生了什么事?

When you declare a read-only variable without initializing it you have to make sure that each execution path will have a value in this read-only variable.当你声明一个只读变量而不初始化它时,你必须确保每个执行路径在这个只读变量中都有一个值。 It means that Kotlin makes sure if your read-only variable was or was not initialized in every place it is used and raises errors if the variable is used inappropriately.这意味着 Kotlin 会确保您的只读变量是否在每个使用它的地方都进行了初始化,并在该变量使用不当时引发错误。

Here you have only one execution path as there are no when or if statements that can split execution into several possible paths.这里只有一个执行路径,因为没有可以将执行拆分为多个可能路径的whenif语句。

class Solution {
    fun love(){
        val message : String
        message = "love"   // Kotlin knows that `message` was not yet initialized
        message = "hate"   // Kotlin knows that `message` was yet initialized! It does not allow to modify the value.
    }
}

Here is what Kotlin documentation says:这是 Kotlin 文档所说的:

... it is also possible (but discouraged) to split the declaration and the initial assignment, and even to initialize in multiple places based on some condition. ...也可以(但不鼓励)拆分声明和初始赋值,甚至根据某些条件在多个地方初始化。 You can only read the variable at a point where the compiler can prove that every possible execution path will have initialized it.您只能在编译器可以证明每个可能的执行路径都已初始化它的时候读取变量。 If you're creating a read-only variable in this way, you must also ensure that every possible execution path assigns to it exactly once.如果您以这种方式创建只读变量,您还必须确保每个可能的执行路径只分配给它一次。

Example of an execution path执行路径示例

Using when or if statement you create two or more execution paths.使用whenif语句可以创建两个或多个执行路径。 Execution paths can be presented as a graph, I'll use #number as a node number .执行路径可以用图形表示,我将使用 #number 作为节点编号 Example:例子:

class Solution {
    fun love(){
        // #1
        val message : String
        if (System.currentTimeMillisec() % 2 == 0) {
            message = "Not empty"      
            // #2
        }

        if (message.isEmpty) { // Error! Message could be not initialized at this point! 
            println("Empty message")
            // #3
        }
    }
}

Looking at this example, that does not compile , we can calculate at least 3 execution paths.看这个例子,那不编译,我们至少可以计算出3条执行路径。

  1. #1 (none of the if statements was entered. All conditions are false ) #1(没有输入 if 语句。所有条件都为false
  2. #1 -> #2 #1 -> #2
  3. #1 -> #3 #1 -> #3

Kotlin can calculate these paths and check if the message variable is initialized in every path it is used. Kotlin 可以计算这些路径并检查message变量是否在它使用的每个路径中初始化。 As we can see, as soon as you reach the evaluation of the second if statement (in case of first and third paths) your program will crash because the message has no value.正如我们所看到的,一旦您到达第二个if语句的评估(在第一个和第三个路径的情况下),您的程序就会崩溃,因为message没有价值。 It has no address in memory and a computer which runs this program does not know how to get a value from an address that does not exist.它在内存中没有地址,运行该程序的计算机不知道如何从不存在的地址获取值。

Now, let's modify this code to make it work:现在,让我们修改此代码以使其工作:

class Solution {
    fun love(){
        // #1
        val message : String
        if (System.currentTimeMillisec() % 2 == 0) {
            message = "Not empty"      
            // #2
        } else {
            message = ""
            // #3
        }

        if (message.isEmpty) { // Error! Message could be not initialized at this point! 
            println("Empty message")
            // #4
        }
    }
}

Execution paths:执行路径:

  1. #1 -> #2 #1 -> #2
  2. #1 -> #3 -> #4 #1 -> #3 -> #4

In this example, Kotlin is sure that the message read-only variable is initialized because there is a 100% chance that one of node 2 or node 3 will be executed.在此示例中,Kotlin 确定message只读变量已初始化,因为节点 2 或节点 3 之一将被执行的可能性为 100%。 Right after the line where the message gets its initial value (initialized) Kotlin treats this variable as a read-only variable with a value.message获取其初始值(初始化)的那一行之后,Kotlin 将此变量视为具有值的只读变量。

Questions are welcome.欢迎提问。 I will try to simplify this answer.我会尽量简化这个答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM