kotlin, how to add extension function to already defined class companion object - kotlin

i want to add some extension function to an already defined class‘s companion object, like
fun Toast.Companion.showImageToast(str : String) {
}
and also i like to do the same thing on interfaces, e.g
fun Runnable.Companion.mainHandler() {
}
I've consulted the documentation, only to find syntax for define extension function for companion object in a user defined class, not for class that don't have a companion object
can i have any chance to do this in kotlin ?

In Kotlin 1.0, if a class does not define a companion object, it is not possible to define extension functions for that companion object. It's also not possible to define extension functions for Java classes and interfaces such as Runnable.

Related

How to understand Kotlin Functional Interface with companion object inside?

I would like to get some help to understand a Kotlin code snippet about functional interface used in Http4k org.http4k.core package
typealias HttpHandler = (Request) -> Response
fun interface Filter : (HttpHandler) -> HttpHandler {
companion object
}
I don’t understand the Filter interface, especially the companion object part. A typical functional interface is like this
fun interface IntPredicate {
fun accept(i: Int): Boolean
}
And you can create a lambda isEven
val isEven = IntPredicate { it % 2 == 0 }
According to this simple example, it looks like the interface Filter extends another interface (HttpHandler) -> HttpHandler? Then it defines a function signature companion object? Is this correct? What does the part companion object really mean?
Filter extends (HttpHandler) -> HttpHandler and the function type (HttpHandler) -> HttpHandler has a single abstract method (operator) - invoke - implicitly declared, like this:
operator fun invoke(HttpHandler): HttpHandler
So that is the function signature for the functional interface, not companion object.
companion object means what it has always meant - a companion object declaration. The companion object might seem empty, just from looking at the code you showed, and it makes one wonder what its purpose is. If you have removed the declaration, the functional interface would still have compiled, and can be used just like a functional interface representing the function type (HttpHandler) -> HttpHandler.
If you look further down the file, however, you'll see that there is (at least) one extension function declared on the companion object:
val Filter.Companion.NoOp: Filter get() = Filter { next -> { next(it) } }
This allows you to do val noOp = Filter.NoOp for example, so the companion object isn't that pointless.

Kotlin: Multiple named companion objects

I have a class which impliments both the java.io.Serializable and android.os.Parcelable.
These classes require companion objects of:
companion object CREATOR : Parcelable.Creator<MyClass> {
override fun createFromParcel(parcel: Parcel): MyClass
...
}
and
companion object {
private val serialVersionUid: Long = 123
}
The trouble is that I can't have both these companion objects because that causes a only one companion object per class exception.
How can I have two companion objects with different names in the same class?
May be you misunderstood Java examples.
public static Parcelable.Creator<SDFileDir> CREATOR = ...;
public static long serialVersionUid = 123;
In Java - yes, it is separated static object. You can place any count of static fields in class.
In Kotlin there should be only one static object (it is called Companion here). But it is like one more class here. So all new static fields should be inside of it.
companion object {
#JvmField
val CREATOR: Parcelable.Creator<SDFileDir> = ...
val serialVersionUid: Long = 123
}
There is one more thing: annotation #JvmField to work with Java correctly.
I can suggest two solutions to this problem:
As #Ircover said - You can declare the CREATOR (which is simply a static field in Java) inside your companion object alongside your constants, but you'll need to mark in with #JvmField annotation to work as inteded (as it is called from Java)..
You do not necessarily need the companion object for the constant value, it (it won't work with serialVersionUid in your case, as it MUST be inside the class for Java serialization to work) can be moved to a separate object, to a companion object of another class or even inside any .kt file body (outside the class)..
In fact, companion object in kotlin doesn't correspond to static object in Java, they merely share similar funtionality.
In Java, there are only two concepts involved: the class and its static object.
In Koltin, we are dealing with three concepts: the class, the companion object, and the property of the companion object.
The way we access the property of the companion object is the same as accessing the static object in Java, but in Kotlin, there is an extra layer between the class and the inner property, that is the companion object.
In your case, you are not demanding two companion objects, but two properties of one companion object, so just place these two properties in one companion object.

Is a Kotlin Companion Object just a way to add functions from an interface?

I am reading the Kotlin in Action book and trying to understand Companion Objects better, are there any other uses for Companion Ojbects other than adding method implementations from an interface/abstract class?
I came across a way of instantiating an object which only works if the class is abstract:
fun main(args: Array<String>) {
Fruit.showColor()
}
class Fruit(val name: String) {
companion object : Apple()
}
abstract class Apple {
fun showColor(){
print("I am an apple")
};
}
My mental model for companion object is language level support for safe singletons. i.e. instead of static methods on a class for Factory or Util methods, you can provide those related methods on the Singleton companion object.
The Companion status gives you a lot of default scoping wins that are similar to the java class with static methods.
Your example seems invalid, because why is the Fruit "singleton" an Apple?

What is the point of naming a companion object in kotlin

The documentation for companion objects has the following example
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
Here Factory is the name of the companion object. It then goes on to say:
The name of the companion object can be omitted, in which case the name Companion will be used:
However there is no example that I can see that uses the name of the companion object.
Since you can only have one companion object per class (otherwise you get a Only one companion object is allowed per class error) the name feels like some pretty useless syntactic sugar to me.
What can the name of the companion object actually be used for?
Why would one bother to use any name for it?
You can use the name of the companion like:
MyClass.create() // not via companion name
MyClass.Companion.create() // via default companion name
MyClass.Factory.create() // via companion name
The name is maybe not that important for Kotlin, because you can just access the method without knowing that there is a companion object (line one above). It is more like a personal style, if you want to make the access to such functions more explicit.
But for java interop it makes a difference, because you have to access the function via the companion name:
MyClass.Factory.create(); // with named companion
MyClass.Companion.create(); // with unnamed comanion
Well, companion objects in Kotlin are not just syntactic sugar. They are actually a type. They are able to do much more thing, and need not to be see as just replacement of static.
You can actually extend class or implement an interface. See an example below.
open class Super {
open fun sayHello() {
println("Hello")
}
}
class Some {
companion object Child : Super() {
override fun sayHello() {
super.sayHello()
println("Hello from companion object")
}
}
}
fun main() {
Some.Child.sayHello()
}
If you do not use an explicit name, the companions name is Companion, thus it can be omitted, like you already quoted.
Sometimes you may want to have an explicit name in your calls, which would be MyClass.Factory.create() in your example. For namespace reasons maybe.
I don't see a many reasons to name a companion object, either. Except if you care about Java interop with your Kotlin code. Then, you need to explicitly write the companions name.
Another reason you might care about the name is, when you define an extension function on it:
fun MyClass.Companion.ext() = "myext"
In this case, it can be clearer when it has a name like Factory, on which specific factory methods are added via extension.
However there is no example that I can see that uses the name of the companion object.
class Person(val name: String) { companion object Loader {
fun fromJSON(jsonText: String): Person = ... }
}
>>> person = Person.Loader.fromJSON("{name: 'Dmitry'}") >>> person.name
Dmitry
>>> person2 = Person.fromJSON("{name: 'Brent'}") >>> person2.name
Brent

Can extension functions be called in a "static" way?

Is it possible to create an extension function and call it as if it were static?
For Example...
fun System.sayByeAndExit() {
println("Goodbye!")
System.exit()
}
fun main(args: Array<String>) {
System.sayByeAndExit() // I'd like to be able to call this
}
I know that the code sample doesn't work...
I understand that kotlin's extension functions are resolved statically, as mentioned in the Kotlin Reference (Extension Functions), but this does not mean they can be called as if they were static functions within a class (in a Java sense).
I also understand that this code will not work because there is no instance of System to pass into the method that the compiler will generate; therefore it won't compile.
Why would I want this?
Some of you might be wondering why this behaviour is desirable. I can understand why you would think that is isn't, so here are some reasons:
It has all of the benefits that standard extension functions give.
An instance of the class doesn't need to be created just to access the extra functionality.
The functions can be accessed from an application-wide context (provided the class is visible).
To summarise...
Does Kotlin have a way to "hook" a static function onto a class? I'd love to know.
You are really asking for "extension functions for a Class reference" or "adding static methods to existing classes" which was covered by another question here: How can one add static methods to Java classes in Kotlin which is covered by a feature request KT-11968
Extension functions cannot be added to anything that does not have an instance. A reference to a Class is not an instance and therefore you cannot extend something like java.lang.System. You can however extend a companion object of an existing class. For example:
class LibraryThing {
companion object { /* ... */ }
}
Allows you to extend LibraryThing.Companion and therefore calling some new myExtension() method would look like you are extending the Class reference itself, when really you are extending the singleton instance of the companion object:
fun LibraryThing.Companion.myExtension() = "foo"
LibraryThing.Companion.myExtension() // results in "foo"
LibraryThing.myExtension() // results in "foo"
Therefore you might find some Kotlin libraries add empty companion objects just for this case. Others do not, and for those you are "out of luck." Since Java does not have companion objects, you cannot do the same for Java either.
The other commonly requested feature is to take an existing Java static method that accepts an instance of a class as the first parameter, and make it behave as an extension function. This is tracked by issues KT-5261, KT-2844, KT-732, KT-3487 and probably other feature requests.
You can define extension function for an object and use it from system-wide context. An object will be created only once.
object MyClz
fun MyClz.exit() = System.exit(0)
fun main(args: Array<String>) {
MyClz.exit()
}
Or
class MyClz {
companion object
}
fun MyClz.Companion.exit() = System.exit(0)
fun main(args: Array<String>) {
MyClz.exit()
}