Reputation: 185
When i reach the companion object section in the ebook "Kotlin in action" it said that:
"if you need to write a function that can be called without having a class instance but needs access to the internals of a class, you can write it as a member of an object declaration inside that class"
As my understanding this means a function of the companion object can access the method and properties of the class that contain it. But when i try to implement this i can't access the members of the class from its companion object'function:
class Normal() {
var name: String = "hallo"
companion object {
fun printName() {
println(name) // ERROR!!! unresolved reference name
}
}}
Did i misunderstood about this concept?
Upvotes: 6
Views: 4254
Reputation: 119
In Kotlin, if you want to write a function or any member of the class that can be called without having the instance of the class then you can write the same as a member of a companion object inside the class. So, by declaring the companion object, you can access the members of the class by class name only(which is without explicitly creating the instance of the class).
fun main(){
println(Demo.name2)
println(Demo.sub(55,25))
}
class Demo{
companion object{
var name2 = "Ram Singh"
fun sub(num1:Int, num2:Int):Int{
return (num1 - num2)
}
}
}
Upvotes: 0
Reputation: 1084
Method inside companion
are kind of static by default(compared to Java & also this is how you achieve static kind of things in Kotlin) and you can not access normal variable from static method.
Same is happening here.
Edit:-
The definition in book is confusing, A companion object is not part of an instance of a class. You can't access members from a companion object, just like in Java you can't access members from a static method. But in case of utility classes where you just need to perform some operation you can call Static method which create a new instance of class and the perform some functions.
For example you can check answer by @user8320224, I am also quoting his code here,
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
}
}
}
Upvotes: 7
Reputation: 17677
A companion object is the same as "static" in Java. It doesn't actually have any instance of your class in it. So if your printname()
method just said println("Hello again!")
you could do the following:
println(Normal().name) // creates a new instance of Normal class and prints "hallo"
Normal.printname() // Does not create a new instance of Normal class but instead just prints "Hello again!" since we can access static methods without requiring an instance of a class itself.
Note that we didn't actually create a new Normal in that second line (no constructor brackets). The printname() method can be thought of as belonging to the definition of a class, rather than an example or instance of that class.
It's rather like the manual for a car; it can reference and talk about the internals of a car, but you need to have an actual car to do anything fun with the manual.
We can access the internals of an instance of the class, if we have one. So passing in an instance of the class would work:
class Normal() {
private var name: String = "hallo"
companion object {
fun printName(normal : Normal) {
println(normal.name) // Note that I made the "name" var private
}
}}
The companion object can also access anything that's within the companion object itself, so this would also work:
class Normal() {
companion object {
private var name: String = "hallo"
fun printName() {
println(name) // Note I moved the "name" var into the companion object
}
}}
And you can combine these:
class Normal() {
private var name: String = "Vilpe89"
companion object {
private var greeting: String = "Hello "
fun printName(normal : Normal) {
println("$greeting ${normal.name}!")
}
}}
Now you could call the above code like this:
Normal.printname(Normal()) // uses Normal's companion object
// method on an instance of Normal,
// and prints "Hello Vilpe89!"
This is very different to what would happen if they were separate classes:
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.
}
}
Upvotes: 1
Reputation: 4702
companion object
is the same as public static final class
in Java. Therefore you can't access to var name.
Maybe this will help you:
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)
}
}
}
Now you can use this in Kotlin:
Normal.name = "new name"
Normal.printName()
and if you want to use this in Java, then:
Normal.setName("new name");
Normal.printName();
Upvotes: 1
Reputation: 228
Static members have access to the internals of a class, for example private members
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
}
}}
Upvotes: 3