当我到达电子书中的伴侣对象部分" Kotlin in action"它说:
" 如果你需要编写一个可以调用的函数 如果没有类实例但需要访问类的内部,则可以将其写为该类中对象声明的成员"
正如我的理解,这意味着伴侣对象的一个功能可以访问包含它的类的方法和属性。但是,当我尝试实现这一点时,我无法从其伴随对象'函数访问该类的成员:
class Normal() {
var name: String = "hallo"
companion object {
fun printName() {
println(name) // ERROR!!! unresolved reference name
}
}}
我误解了这个概念吗?
答案 0 :(得分:4)
默认情况下companion
内部的方法是静态的(与Java相比,这也是你在Kotlin中实现静态事物的方式),你无法从静态方法中访问常规变量。
同样发生在这里。
编辑: -
书中的定义令人困惑,伴侣对象不是类实例的一部分。您无法从协同对象访问成员,就像在Java中一样,您无法从静态方法访问成员。但是对于只需要执行某些操作的实用程序类,可以调用静态方法,该方法创建一个新的类实例并执行一些函数。
例如,您可以按@user8320224查看答案,我也在这里引用他的代码,
class Normal {
private var name: String = "hallo"
private fun printName() {
println(name)
}
companion object {
fun factoryNormal(): Normal {
val normal = Normal()
normal.printName()
normal.name = "new name"
normal.printName()
return normal
}
}
}
答案 1 :(得分:2)
静态成员可以访问类的内部,例如私有成员
class Normal() {
private var name: String = "hallo"
private fun printName() {
println(name)
}
companion object {
fun factoryNormal(): Normal {
val normal = Normal()
normal.printName()
normal.name = "new name"
normal.printName()
return normal
}
}}
答案 2 :(得分:1)
companion object
与Java中的public static final class
相同。因此,您无法访问 var name 。
也许这会对你有所帮助:
class Normal() {
companion object {
@JvmStatic
var name: String = "hallo"
// This annotation will be helpful if you are calling
// this from Java, so it goes like Normal.printName();
@JvmStatic
fun printName() {
println(name)
}
}
}
现在你可以在Kotlin中使用它了:
Normal.name = "new name"
Normal.printName()
如果你想在Java中使用它,那么:
Normal.setName("new name");
Normal.printName();
答案 3 :(得分:1)
伴侣对象与Java中的“static”相同。它实际上没有任何类的实例。因此,如果您的printname()
方法只是说println("Hello again!")
,则可以执行以下操作:
println(Normal().name) // creates a new Normal class and prints "hallo"
Normal.printname() // Does not create a new normal class but just prints "Hello again!"
请注意,我们实际上并没有在第二行创建新的Normal(没有构造函数括号)。 printname()方法可以被认为属于类的定义,而不是示例或该类的实例。
它更像是汽车的手册;它可以参考和讨论汽车的内部结构,但你需要有一辆真正的汽车才能用手册做任何有趣的事情。
如果我们有一个实例,我们可以访问该类实例的内部。所以传入一个类的实例会起作用:
class Normal() {
private var name: String = "hallo"
companion object {
fun printName(normal : Normal) {
println(normal.name) // Note that I made the "name" var private
}
}}
伴侣对象也可以访问伴随对象本身内的任何内容,因此这也有效:
class Normal() {
companion object {
private var name: String = "hallo"
fun printName() {
println(name) // Note I moved the "name" var into the companion object
}
}}
你可以将这些结合起来:
class Normal() {
private var name: String = "Vilpe89"
companion object {
private var greeting: String = "Hello "
fun printName(normal : Normal) {
println("$greeting ${normal.name}!")
}
}}
现在您可以像这样调用上面的代码:
Normal.printname(Normal()) // uses Normal's companion object
// method on an instance of Normal,
// and prints "Hello Vilpe89!"
这与如果它们是单独的类会发生什么非常不同:
class Normal() {
private var name: String = "Vilpe89"
}
class Greeting() {
private var greeting: String = "Hello "
fun printName(normal : Normal) {
println("$greeting ${normal.name}!") // This won't compile, because
// Greeting can't see normal.name
// if it's private.
}
}