Statically importing Kotlin Companion methods? - kotlin

tl:dr; Is it possible to import a method inside a companion object of another class, without qualifying the import with Companion? That is, is there any possible way I can say import Bar.toFoo instead of import Bar.Companion.toFoo, assuming toFoo is a method on Bar's companion object?
We're migrating a class from Java to Kotlin. Our class looks like this:
class Bar {
static Foo toFoo() {
return new Foo();
}
}
And then, to use it, from a class that happens to be Kotlin, we say something like:
import Bar.toFoo;
// ...
Bar().convert(toFoo()); // like a Java 8 Collector
// ...
When we convert Bar to Kotlin, it looks like this:
class Bar {
companion object {
#JvmStatic fun toFoo() = Foo()
}
}
We'd like the calling code to work without modification, however
import Bar.toFoo
no longer works, even with #JvmStatic! Instead, we have to update it to
import Bar.Companion.toFoo
which we'd rather not have to do -- we want to switch the Bar class to Kotlin without updating the callers.
Thoughts? We're using Kotlin 1.1.2-2.

Unlike Java, Kotlin does not allow you to call static members via instance reference. Java dispatches these members based on the compile time declaration, so in
class Bar {
static Foo toFoo() { return new Foo(); }
}
class Foo extends Bar {
static Foo toFoo() { return new Foo(); }
}
class Baz {
void test() {
Bar fooAsBar = new Foo();
Foo foo = fooAsBar.toFoo();
}
}
In Java, fooAsBar.toFoo() will actually call Bar.toFoo() (the declared type) and not Foo.toFoo() (the runtime type). This is a source of misunderstanding and not good programming practice, so Kotlin does not support it.
However, you can define an extension function on Bar:
fun Bar?.toFoo() = Bar.toFoo()
Then you can call
val foo = fooAsBar.toFoo()

Related

Alternative way for kotlin static methods

Im kinda new to Kotlin and I was wondering how I could make a static method.
Test.foo() //I want to do this from somewhere else in the program
open class Test() {
private giorgor: String? = null
fun foo(value:String) {
giorgor = value
}
}
I need to change the value of giorgor from somewhere else in the code and I thought I could use a static method to do that but I dont know how. Test also needs to be an open class
The equivalent of a static method in Kotlin is a method in the companion object, e.g.:
class Test() {
// …
companion object {
fun foo() = // …
}
}
You can access it in the obvious way:
fun main() {
Test.foo()
}
However, the bits of code I've elided make me suspect that this isn't exactly what you want: your example has foo() referring to a property of Test — and because each instance of Test has its own version of that property, it would need to refer to an specific instance. (And if you had an instance, there would be no need of the companion class — you could just make it a regular method of Test.)
In a comment, you refer to a Minecraft plug-in — can you explain what requirements that has?
BTW, a simpler alternative to the companion object is just a top-level method:
fun foo() = // …
From the same file, you can call it as foo(); from elsewhere, you'd call it as <Filename>Kt.foo() (since the compiler generates a dummy classname for top-level functions and properties, based on the filename). However, the same issues apply to that too.
If I'm understanding you correctly, you want an object instead of a class
object Test {
var giorgor: String = "jiorgor"
fun foo() = println(giorgor)
}
fun main() {
Test.foo()
}
One way to do this is by making the class open or abstract and adding this
companion object Default: Test()
This makes it act like every method of Test() is inside the companion object Default.
If you wanted, you could also override an open method and make it have a different output for when it is used statically:
fun main() {
val test = Test()
test.foo() //Output: "jiorgor"
Test.foo() //Output: "static jiorgor"
}
public open class Test() {
var giorgor: String = "jiorgor"
open fun foo() = println(giorgor)
companion object Default : Test() {
override fun foo() = println("static jiorgor")
}
}

Kotlin implement `fun` as `val` (Similar to Scala implementing a `def` as `val`)

In Scala you can define a trait with an undefined def to be implemented in the implementing class. Additionally a def can be implemented as a def or as a val.
trait Foo { def bar: Int }
class Baz(val bar: Int) extends Foo // ok
For Context
val has the same meaning in Scala and Kotlin
fun and def are more or less the same in Scala and Kotlin
trait and interface are more or less the same in Scala and Kotlin.
The advantage here is that some implementations of trait can return a static value for bar that is set when the class initializes, and some implementations can generate the value every time bar is accessed.
Is there similar functionality built into Kotlin?
I already tired implementing a fun as a val and that does not work. I currently have the code below, but it feels like there is more boiler plate here than necessary.
interface Foo {
fun bar(): Int
}
class Baz : Foo {
private val _bar: Int = TODO("Some heavy init function.")
override fun bar(): Int = _bar
}
It can be done with a val property instead of a function. When you define a property with just = and no get(), the initialization code is called a single time and assigned to the backing variable, so when the property is accessed, it simply reads the value stored in the backing variable without computing it again:
interface Foo {
val bar: Int
}
class Baz : Foo {
override val bar: Int = TODO("Some heavy init function.")
}
And the interface gives you the flexibility to make it something that is computed on demand (possibly different each time accessed) using a custom getter:
class Baz : Foo {
override val bar: Int get() = Random.nextInt(10)
}
Or computed lazily using a property delegate (the first time it is accessed instead of at class instantiation time):
class Baz : Foo {
override val bar: Int by lazy { TODO("Some heavy init function.") }
}
Or you can upgrade it to be a var and allow external classes to overwrite what is set in the property:
class Baz : Foo {
override var bar: Int = 5
}
Or only internal to the class:
class Baz : Foo {
override var bar: Int = 5
private set
}
With the custom getter, you could do something more complicated involving backing properties, similar to your code with the fun. Or you can design your own property delegate if there's a pattern you use repeatedly.

Returning reference to a singleton class instance within its functions

In the following code I would like to set a reference to the class instance so that static functions can return a reference to it:
open class TestRunner {
init {
instance = this
}
companion object {
private lateinit var instance: TestRunner
fun addTestSetups(vararg testSetups: () -> TestSetup): TestRunner {
for (setup in testSetups) {
testsSetups.add(setup)
}
return instance
}
}
}
But setting instance = this is not allowed. How can I return an instance of the class from a function while keeping the class as a singleton?
If I get you right, you want something like this:
abstract class TestRunner {
companion object : TestRunner()
}
This seems to work. Instead of keeping a variable that holds a reference to the class, simply referencing the name of the class is sufficient. However, to return an instance of the class from functions, the return type must be Companion:
open class TestRunner {
companion object {
fun addTestSetups(vararg testSetups: () -> TestSetup): Companion {
for (setup in testSetups) {
testsSetups.add(setup)
}
return TestRunner
}
}
}
This is not a true singleton because you can still create a new instance if you did this:
val testRunner = TestRunner()
However, if you never create an instance but only refer to the functions statically, it does behave like a singleton and the state of any private variables inside the companion object will still be maintained.
Update:
I came across this code on the Android developer site that shows an example of a class that is setup as a singleton:
class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
private val stockManager: StockManager = StockManager(symbol)
private val listener = { price: BigDecimal ->
value = price
}
override fun onActive() {
stockManager.requestPriceUpdates(listener)
}
override fun onInactive() {
stockManager.removeUpdates(listener)
}
companion object {
private lateinit var sInstance: StockLiveData
#MainThread
fun get(symbol: String): StockLiveData {
sInstance = if (::sInstance.isInitialized) sInstance else StockLiveData(symbol)
return sInstance
}
}
}
But it should be pointed out that this example requires functions that need to return an instance to first check if the instance variable is set and if not, create a new instance. I'm not sure what the point of that is since to call the function you already have an instance. So why bother create a new instance? Doesn't seem to make any sense.
object in Kotlin is the singleton, not the class its defined within. A companion object has the extra convenience of allowing you to call it by the name of that outer class. But it otherwise shares no hierarchy with it.
To make your class subclassable, you can't define the functions in the companion object. But you can make the class abstract so it can't be instantiated unless subclassed. Then make your companion object extend the abstract class so it will have all those functions available.
abstract class TestRunner{
open fun addTestSetups(vararg testSetups: () -> TestSetup): TestRunner{
//...
return this
}
companion object: TestRunner()
}
Usage:
TestRunner.addTestSetups(someTestSetup)
Note that your singleton is not an instance of TestRunner. It is a singleton instance of a subclass of TestRunner. But since you define no extra functions and override nothing, it behaves exactly like a TestRunner.
If you want a subclass:
abstract class ExtendedTestRunner: TestRunner() {
fun someOtherFunction() {}
companion object: ExtendedTestRunner()
}
The companions are not being subclassed, but their abstract parents can be.

Util class in Kotlin (Best Approach)? [duplicate]

This question already has answers here:
Utils class in Kotlin
(3 answers)
Closed 1 year ago.
I was playing with Kotlin, and creating Util class with different ways. I am approaching a way that works best for calling by either Kotlin or Java.
Now I have created many types of Util. And now I am very confused which is best to use and most important why? I am finding best way considering Heap, Memory, Performance.
My question may look stupid for you guys, but I am in maze and can't come to a solution myself.
Here is my playground.
I have created 5 Kotlin files. in which I have put foo() method. and tried to call by Kotlin and Java.
Calling class Bar.kt
class Bar {
fun bazz() {
UtilClass.instance.foo()
UtilClassObject.UtilClassObject.foo()
UtilCompanionObject.foo()
UtilFileObject.foo()
foo() // from UtilFile
}
}
Calling class Qux.java
public class Qux {
public void bazz() {
UtilClass.Companion.getInstance().foo();
UtilClassObject.UtilClassObject.INSTANCE.foo();
UtilFileKt.foo();
UtilFileObject.INSTANCE.foo();
UtilCompanionObject.Companion.foo();
}
}
And here is the maze that makes me confused to choose best.
UtilClass.kt
class UtilClass {
fun foo() { ... }
companion object {
val instance = UtilClass()
}
}
UtilClassObject.kt
class UtilClassObject {
object UtilClassObject {
fun foo() { ... }
}
}
UtilCompanionObject.kt
class UtilCompanionObject {
companion object {
fun foo() { ... }
}
}
UtilFile.kt
fun foo(){ ... }
UtilFileObject.kt
object UtilFileObject {
fun foo() { ... }
}
It may take to answer my question and explaining it well. So I really appreciate your efforts in advance.
All options are present on the Kotlin reference page for interop between Kotlin and Java: https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html
Your options to call from Java something on class MyUtil and call it without an instance such as MyUtil.foo() then you would simply do one of the two options:
// smallest byte code,
// static invocation of foo() from Kotlin side,
// also static call from Java to foo()
object MyUtil {
#JvmStatic fun foo() { ... }
}
or
// creates two classes,
// static lookup of companion followed by virtual call on that instance to foo() from Kotlin,
// Java is a static call to foo()
class MyUtil {
companion object {
#JvmStatic fun foo() { ... }
}
}
And you would call it the same from Kotlin MyUtil.foo(). This is specifically the model of making a Kotlin method static.
Both examples look the same from Java in that they are just direct static calls to a static method. From Kotlin the first example is a static call as well, the second looks up an instance of the companion first and then does a virtual call on the method. The Second example creates two classes, the other only creates a single class.
The other options you present are not more efficient and are uglier syntax. Based on smallest byte code, fewest classes, and fastest performance pick the first example that is 1 class only and all static calls.

Kotlin static methods and variables

I want to be able to save a class instance to a public static variable but I can't figure out how to do this in Kotlin.
class Foo {
public static Foo instance;
public Foo() {
instance = this;
}
}
Update: since this answer is getting a decent amount of upvotes, I really wanted to say that you shouldn't do the below, but instead just use object Foo { ... }, like Roman rightly points out in the comment.
Previous answer:
The closest thing to Java's static fields is a companion object. You can find the documentation reference for them here: https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects
Your code in Kotlin would look something like this:
class Foo {
companion object {
lateinit var instance: Foo
}
init {
instance = this
}
}
If you want your fields/methods to be exposed as static to Java callers, you can apply the #JvmStatic annotation:
class Foo {
companion object {
#JvmStatic lateinit var instance: Foo
}
init {
instance = this
}
}
It looks that you want to define a singleton object. It is supported in Kotlin as a first-class concept:
object Foo {
...
}
All the boilerplate code with static field and constructor is taken care by the Kotlin automatically. You don't have to write any of that.
From the Kotlin code you can refer to the instance of this object simply as Foo. From the Java code you can referer to the instance of this object as Foo.INSTANCE, because the Kotlin compiler automatically creates the corresponding static field named INSTANCE.
first you create a simple class then after create a block followed by companion object keyword
for example:
class Test{
companion object{
fun getValue(): String{
return "Test String"
}
}
}
you can call this class function using class name dot function name
for example:
// here you will get the function value
Test.getValue()
You can create a companion object for the class, and if you want the field to be static you can use the annotation #JvmStatic. Companion object have access to private members of the class it is companion for.
See below an example:
class User {
private lateinit var name: String
override fun toString() = name
companion object {
#JvmStatic
val instance by lazy {
User().apply { name = "jtonic" }
}
}
}
class CompanionTest {
#Test
fun `test companion object`() {
User.instance.toString() shouldBe "jtonic"
}
}