在哪种情况下,在Kotlin构造函数参数中需要val/var?

Kor*_*ere 22 android kotlin

正确代码:

class MainActHandler(val weakActivity: WeakReference<Activity>): Handler() {
    override fun handleMessage(msg: Message?) {
        val trueAct = weakActivity.get() ?: return
        if (msg?.what == ConversationMgr.MSG_WHAT_NEW_SENTENCE){
            val sentence = msg.obj as String?
            trueAct.conversation.text = sentence
        }
        super.handleMessage(msg)
    }
}
Run Code Online (Sandbox Code Playgroud)

无法解析代码:

class MainActHandler(weakActivity: WeakReference<Activity>): Handler() {
    override fun handleMessage(msg: Message?) {
        val trueAct = weakActivity.get() ?: return
        if (msg?.what == ConversationMgr.MSG_WHAT_NEW_SENTENCE){
            val sentence = msg.obj as String?
            trueAct.conversation.text = sentence
        }
        super.handleMessage(msg)
    }
}
Run Code Online (Sandbox Code Playgroud)

无法解析代码截图

唯一的区别是"val"已被删除,无法解决.

这可能很重要,因为它是一个内在阶级.

构造函数参数中没有"val/var"的这一个类正在工作:

class BookInfo(convrMgr: ConversationMgr, id: String, queue: RequestQueue, queueTag:String) {

val TAG = "BookInfo"
var title: String? = ""

init {
    val url = "https://api.douban.com/v2/book/$id"
    // Request a string response from the provided URL.
    val stringRequest = StringRequest(Request.Method.GET, url,
            Response.Listener<String> { response ->
                Log.d(TAG + " Response", response.substring(0))
                // Parse JSON from String value
                val parser = Parser()
                val jsonObj: JsonObject =
                        parser.parse(StringBuilder(response.substring(0))) as JsonObject
                // Initial book title of book properties.
                title = jsonObj.string("title")
                Log.d(TAG + " Book title", title)
                convrMgr.addNewMsg(title)
            },
            Response.ErrorListener { error -> Log.e(TAG + " Error", error.toString()) })
    // Set the tag on the request.
    stringRequest.tag = queueTag
    // Add the request to the RequestQueue.
    queue.add(stringRequest)
}
Run Code Online (Sandbox Code Playgroud)

}

如果我在"queue:RequestQueue"之前添加var/val,我会得到建议:

"构造函数参数永远不会被用作属性.此检查会报告可以删除'val'或'var'的主构造函数参数.在主构造函数中不必要地使用'val'和'var'会占用不必要的内存."

我对此感到困惑.

Bak*_*aii 38

当你在构造函数中编写val/时var,它在类中声明了一个属性.当您不编写它时,它只是传递给主构造函数的参数,您可以在其中访问init块中的参数或使用它来初始化其他属性.例如,

class User(val id: Long, email: String) {
    val hasEmail = email.isNotBlank()    //email can be accessed here
    init {
        //email can be accessed here
    }

    fun getEmail(){
        //email can't be accessed here
    }
}
Run Code Online (Sandbox Code Playgroud)

构造函数参数从不用作属性

这个建议是说除了初始化之外你不要使用这个属性.因此,它建议您从类中删除此属性.


Tan*_*.7x 7

构造函数参数必须使用varval在类中其他地方用作属性时使用。如果它们仅用于类初始化,则不必是属性。

在这种情况下,参数必须是属性(varval),因为它在方法中使用:

class A(val number: Int) {
    fun foo() = number
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,该参数仅用于初始化类,因此它不必是属性:

class B(number: Int): A(number) {
    init {
        System.out.println("number: $number")
    }
}
Run Code Online (Sandbox Code Playgroud)


Say*_*der 7

这可能是一个迟到的答案,但魔法就在幕后:

根据@BakaWaii's答案:

放置 var/val 将使该变量成为类的属性,而不放置它将使其仅成为构造函数的参数。

那么这是什么意思,为了理解,让我们看一些代码:

class Test(a: Int){}
Run Code Online (Sandbox Code Playgroud)

现在让我们看看反编译的java代码:

public final class Test {
   public Test(int a) {
   }
}
Run Code Online (Sandbox Code Playgroud)

所以现在如果我尝试使用以下代码a的对象进行访问:Test()

Test t = new Test(10);
t.a //Error 
Run Code Online (Sandbox Code Playgroud)

它会给我错误。Unresolved reference: a。为什么因为a它只是构造函数的参数。

现在,如果我们将 var/val 放入参数中,如下所示:

class Test(var a: Int){}
Run Code Online (Sandbox Code Playgroud)

反编译后的Java代码将变成:

public final class Test {
   private int a;

   public final int getA() {
      return this.a;
   }

   public final void setA(int var1) {
      this.a = var1;
   }

   public Test(int a) {
      this.a = a;
   }
}
Run Code Online (Sandbox Code Playgroud)

因此,它不仅会为您提供一个类属性,还会为您提供用于设置值的 getter/setter。

a现在出现的下一个问题是private如何访问该字段。Java 中的简单答案是你不能,即如果你从 Java 调用 KT 类,你将无法分配alike的值Test(1).a = 10,但必须使用Test(1).setA(5)。但由于 kotlin 内部处理 getters/setters Test(1).a = 5 就可以了。