Can I add Kotlin extension function to Java class? - kotlin

I'm trying to create extension function like this:
fun UHFTAGInfo.toReadUhfTagInfo(): ReadUhfTagInfo {
return ReadUhfTagInfo(this.epc, this.count, this.rssi.toIntOrNull())
}
It is supposed to convert UHFTAGInfo (from java library) to ReadUhfTagInfo (my class in Kotlin).
I'm trying to use it like this:
UHFTAGInfo i = getUHFTAGInfo();
ReadUhfTagInfo ri = i.toReadUhfTagInfo();
At this moment my toReadUhfTagInfo function is at top level, but finally I want to put it in my ReadUhfTagInfo class, like this:
class ReadUhfTagInfo(var epc: String, var cnt: Int, var rssi: Int?)
{
fun UHFTAGInfo.toReadUhfTagInfo(): ReadUhfTagInfo {
return ReadUhfTagInfo(this.epc, this.count, this.rssi.toIntOrNull())
}
}

You can call Kotlin extension functions from Java, sure, but you can't call them with extension function syntax, you must call them like static methods. If you, for example, define
// file: Foo.kt
fun Bar.baz() { ... }
then in Java, you would call this as
FooKt.baz(bar);

I don't think you want to have toReadUhfTagInfo as a member function on the ReadUhfTagInfo class. That would imply that, in order to convert a UHFTAGInfo to a ReadUhfTagInfo, you already need a ReadUhfTagInfo object (which will presumably go unused except to serve as the receiver object.
Extension functions defined inside a class are member extensions and essentially have two receivers.
You can declare extensions for one class inside another class. Inside such an extension, there are multiple implicit receivers - objects whose members can be accessed without a qualifier. An instance of a class in which the extension is declared is called a dispatch receiver, and an instance of the receiver type of the extension method is called an extension receiver.
If you want the extension method to act like a static method in Java (i.e. not require an instance of the enclosing class to execute), then you do the same thing we do with all static methods in Kotlin: We put it in a companion object.
class ReadUhfTagInfo(var epc: String, var cnt: Int, var rssi: Int?)
{
companion object {
fun UHFTAGInfo.toReadUhfTagInfo(): ReadUhfTagInfo {
return ReadUhfTagInfo(this.epc, this.count, this.rssi.toIntOrNull())
}
}
}
As pointed out in the comments, this will still require the name to be imported into the current scope (as all extension methods do), but it won't require a receiver of type ReadUhfTagInfo to call anymore.

Related

Why/How does this extension function work? How to call it without `with`?

While taking the "Kotlin for Java Developers" Coursera course, I came across this construction, where an extension function for a contained instance seems to have access to the containing class' private fields. Note how the Data class is implemented outside of Container and does not have access to Container's fields, but the Data.printMe() extension function can access Container's private containerVal member:
data class Data (val data: String)
class Container (private val containerVal: String, val data: Data){
fun Data.printMe() {
println("data: $data - in container: ${this#Container.containerVal}")
}
}
fun main() {
val c = Container("mycontainer", Data("mydata"))
// Can I call Data.printMe without using `with`?
// val d = c.data.printMe();
with (c) {
// Prints: data: mydata - in container: mycontainer
data.printMe();
}
}
Pretty cool that Data.printMe can access Container's private members. The with(c) is apparently what allows that. I can see lots of use cases for this, just like how in the course example extension functions for a game's Cells can access the containing Board without the Cell class itself being polluted by and tightly coupled with Board.
Does this "approach" have a name? And is there a syntax to call c.data.printMe "directly" without using with? The with documentation doesn't mention this use case.
The printMe() method has two receivers: the dispatch receiver and the extension receiver. The dispatch receiver is the instance of the class in which the extension is declared, and the extension receiver is the instance of the receiver type of the extension method. You are accessing contaiverVal in the context of a Container instance (dispatch receiver), not a Data instance (extension receiver).
If you try to do the opposite and access a private property of the Data class inside the printMe(), you will get a compiler error.
when you define an extension function as a member of a class, it is only usable in the context that class. You can access it inside the class or using a scope function where the context object is available as a lambda receiver (this). Those functions are run, with and apply.

extension function is virtual to dispatch reciever?

In kotlin Declaraing extensions as members, what does it mean "the dispatch of such functions is virtual with regard to the dispatch receiver type, but static with regard to the extension receiver type."
Is this mean that "the extension function doesn't follows its reciever's class type. It follows parameter type(?in this code call method parameter)."
please give your warmhearted and generous advice
open class Base { }
class Derived : Base() { }
open class BaseCaller {
open fun Base.printFunctionInfo() {
println("Base extension function in BaseCaller")
}
open fun Derived.printFunctionInfo() {
println("Derived extension function in BaseCaller")
}
fun call(b: Base) {
b.printFunctionInfo() // call the extension function
}
}
class DerivedCaller: BaseCaller() {
override fun Base.printFunctionInfo() {
println("Base extension function in DerivedCaller")
}
override fun Derived.printFunctionInfo() {
println("Derived extension function in DerivedCaller")
}
}
fun main() {
BaseCaller().call(Base()) // "Base extension function in BaseCaller"
DerivedCaller().call(Base()) // "Base extension function in DerivedCaller" - dispatch receiver is resolved virtually
DerivedCaller().call(Derived()) // "Base extension function in DerivedCaller" - extension receiver is resolved statically
}
Since you have linked the documentation, I take it that you have read the following part
The instance of the class in which the extension is declared is called
dispatch receiver, and the instance of the receiver type of the extension method is called extension receiver.
After you have understood the above terminology, you need to understand following points
If you don't know about virtual methods read this
Extensions are resolved statically. Consider the following code block
fun call(b: Base) {
// This will always call extension function defined on the Base class
// even if you pass an object of Derived class
b.printFunctionInfo() // call the extension function
}
// This calls the printFunctionInfo defined on the Base, even though we pass Derived
DerivedCaller().call(Derived())
Now to your question
the dispatch of such functions is virtual with regard to the dispatch
receiver type, but static with regard to the extension receiver type.
With the Extensions are resolved statically point we have established that no matter which object you pass (Base or Derived) the call function will always invoke an extension function defined on the Base type.
But which extension function will be invoked? one in the Base class or the one in Derived class ?
This depends on the type of object which invokes the call function, if you invoke the call with an Object of Base then the extension in the base class will be invoked and if you use the Derived object then the extension in Derived class will be invoked.

Kotlin data classes contains open functions

I was reading kotlin official tutorial, Under the data class topic, I came up with a following point.
If a supertype has the componentN() functions that are open and return compatible types, the corresponding functions are generated for the data class and override those of the supertype. If the functions of the supertype cannot be overridden due to incompatible signatures or being final, an error is reported;
My Questions are,
1) What is componentN() functions ?
2) Does the data class override the open function automatically ?
3) Is following code correct ?
open class SuperDataClass {
open fun componentN() {
println("from super class")
}
}
data class DataClassExample (var name: String): SuperDataClass() {
//
}
1) What is componentN() functions ?
They are operator functions corresponding to the properties in their order of declaration.
Example:
data class Person(name: String, age: Int)
the class above will have a component1 and a component2 function, allowing the access through destructuring declaration to name and age, in that order.
Take in consideration that componentN function is just to reference 1st, 2nd, 3rd, ..., Nth component. The componentN function itself is never generated.
2) Does the data class override the open function automatically ?
In data class, you are extending from Any class, you aren't overriding automatically any function. componentN functions are generated at compile time.
3) Is following code correct ?
open class SuperDataClass {
open fun componentN() {
println("from super class")
}
}
data class DataClassExample (var name: String): SuperDataClass() {
//
}
Yes, it will compile and will run correctly. But this is only because, as I said before, componentN isn't generated for data classes.
However, in this case a component1 is generated for the property name of DataClassExample. As the quote of the documentation you posted says: if you try this code, you will have an error.
open class SuperDataClass {
open fun component1() {//<-- note this
println("from super class")
}
}
data class DataClassExample (var name: String): SuperDataClass() {
//
}
The specific error is:
[DATA_CLASS_OVERRIDE_CONFLICT] Function 'component1' generated for the data class conflicts with member of supertype 'SuperDataClass'

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()
}

Why do we use "companion object" as a kind of replacement for Java static fields in Kotlin?

What is the intended meaning of "companion object"? So far I have been using it just to replace Java's static when I need it.
I am confused with:
Why is it called "companion"?
Does it mean that to create multiple static properties, I have to group it together inside companion object block?
To instantly create a singleton instance that is scoped to a class, I often write
:
companion object {
val singleton by lazy { ... }
}
which seems like an unidiomatic way of doing it. What's the better way?
What is the intended meaning of "companion object"? Why is it called "companion"?
First, Kotlin doesn't use the Java concept of static members because Kotlin has its own concept of objects for describing properties and functions connected with singleton state, and Java static part of a class can be elegantly expressed in terms of singleton: it's a singleton object that can be called by the class' name. Hence the naming: it's an object that comes with a class.
Its name used to be class object and default object, but then it got renamed to companion object which is more clear and is also consistent with Scala companion objects.
Apart from naming, it is more powerful than Java static members: it can extend classes and interfaces, and you can reference and pass it around just like other objects.
Does it mean that to create multiple static properties, I have to group it together inside companion object block?
Yes, that's the idiomatic way. Or you can even group them in non-companion objects by their meaning:
class MyClass {
object IO {
fun makeSomethingWithIO() { /* ... */ }
}
object Factory {
fun createSomething() { /* ... */ }
}
}
To instantly create a singleton instance that is scoped to a class, I often write /*...*/ which seems like an unidiomatic way of doing it. What's the better way?
It depends on what you need in each particular case. Your code suits well for storing state bound to a class which is initialized upon the first call to it.
If you don't need it to be connected with a class, just use object declaration:
object Foo {
val something by lazy { ... }
}
You can also remove lazy { ... } delegation to make the property initialize on first class' usage, just like Java static initializers
You might also find useful ways of initializing singleton state.
Why is it called "companion"?
This object is a companion of the instances.
IIRC there was lengthy discussion here: upcoming-change-class-objects-rethought
Does it mean that to create multiple static properties, I have to group it together inside companion object block?
Yes. Every "static" property/method needs to be placed inside this companion.
To instantly create a singleton instance that is scoped to a class, I often write
You do not create the singleton instance instantly. It is created when accessing singleton for the first time.
which seems like an unidiomatic way of doing it. What's the better way?
Rather go with object Singleton { } to define a singleton-class. See: Object Declarations
You do not have to create an instance of Singleton, just use it like that Singleton.doWork()
Just keep in mind that Kotlin offers other stuff to organize your code. There are now alternatives to simple static functions e.g. you could use Top-Level-Functions instead.
When the classes/objects with related functionalities belong together, they are like companions of each other. A companion means a partner or an associate, in this case.
Reasons for companionship
Cleaner top-level namespace
When some independent function is intended to be used with some specific class only, instead of defining it as a top-level function, we define it in that particular class. This prevents the pollution of top-level namespace and helps with more relevant auto-completion hints by IDE.
Packaging convenience
It's convenient to keep the classes/objects together when they are closely related to each other in terms of the functionality they offer to each other. We save the effort of keeping them in different files and tracking the association between them.
Code readability
Just by looking at the companionship, you get to know that this object provides helper functionality to the outer class and may not be used in any other contexts. Because if it was to be used with other classes, it would be a separate top level class or object or function.
Primary purpose of companion object
Problem: companion class
Let's have a look at the kinds of problems the companion objects solve. We'll take a simple real world example. Say we have a class User to represent a user in our app:
data class User(val id: String, val name: String)
And an interface for the data access object UserDao to add or remove the User from the database:
interface UserDao {
fun add(user: User)
fun remove(id: String)
}
Now since the functionalities of the User and implementation of the UserDao are logically related to each other, we may decide to group them together:
data class User(val id: String, val name: String) {
class UserAccess : UserDao {
override fun add(user: User) { }
override fun remove(id: String) { }
}
}
Usage:
fun main() {
val john = User("34", "John")
val userAccess = User.UserAccess()
userAccess.add(john)
}
While this is a good setup, there are several problems in it:
We have an extra step of creating the UserAccess object before we can add/remove a User.
Multiple instances of the UserAccess can be created which we don't want. We just want one data access object (singleton) for User in the entire application.
There is a possibility of the UserAccess class to be used with or extended with other classes. So, it doesn't make our intent clear of exactly what we want to do.
The naming userAccess.add() or userAccess.addUser() doesn't seem very elegant. We would prefer something like User.add().
Solution: companion object
In the User class, we just replace the two words class UserAccess with the two other words companion object and it's done! All the problems mentioned above have been solved suddenly:
data class User(val id: String, val name: String) {
companion object : UserDao {
override fun add(user: User) { }
override fun remove(id: String) { }
}
}
Usage:
fun main() {
val john = User("34", "John")
User.add(john)
}
The ability to extend interfaces and classes is one of the features that sets the companion objects apart from Java's static functionality. Also, companions are objects, we can pass them around to the functions and assign them to variables just like all the other objects in Kotlin. We can pass them to the functions that accept those interfaces and classes and take advantage of the polymorphism.
companion object for compile-time const
When the compile-time constants are closely associated with the class, they can be defined inside the companion object.
data class User(val id: String, val name: String) {
companion object {
const val DEFAULT_NAME = "Guest"
const val MIN_AGE = 16
}
}
This is the kind of grouping you have mentioned in the question. This way we prevent the top-level namespace from polluting with the unrelated constants.
companion object with lazy { }
The lazy { } construct is not necessary to get a singleton. A companion object is by default a singleton, the object is initialized only once and it is thread safe. It is initialized when its corresponding class is loaded. Use lazy { } when you want to defer the initialization of the member of the companion object or when you have multiple members that you want to be initialized only on their first use, one by one:
data class User(val id: Long, val name: String) {
companion object {
val list by lazy {
print("Fetching user list...")
listOf("John", "Jane")
}
val settings by lazy {
print("Fetching settings...")
mapOf("Dark Theme" to "On", "Auto Backup" to "On")
}
}
}
In this code, fetching the list and settings are costly operations. So, we use lazy { } construct to initialize them only when they are actually required and first called, not all at once.
Usage:
fun main() {
println(User.list) // Fetching user list...[John, Jane]
println(User.list) // [John, Jane]
println(User.settings) // Fetching settings...{Dark Theme=On, Auto Backup=On}
println(User.settings) // {Dark Theme=On, Auto Backup=On}
}
The fetching statements will be executed only on the first use.
companion object for factory functions
Companion objects are used for defining factory functions while keeping the constructor private. For example, the newInstance() factory function in the following snippet creates a user by generating the id automatically:
class User private constructor(val id: Long, val name: String) {
companion object {
private var currentId = 0L;
fun newInstance(name: String) = User(currentId++, name)
}
}
Usage:
val john = User.newInstance("John")
Notice how the constructor is kept private but the companion object has access to the constructor. This is useful when you want to provide multiple ways to create an object where the object construction process is complex.
In the code above, consistency of the next id generation is guaranteed because a companion object is a singleton, only one object will keep track of the id, there won't be any duplicate ids.
Also notice that companion objects can have properties (currentId in this case) to represent state.
companion object extension
Companion objects cannot be inherited but we can use extension functions to enhance their functionality:
fun User.Companion.isLoggedIn(id: String): Boolean { }
The default class name of the companion object is Companion, if you don't specify it.
Usage:
if (User.isLoggedIn("34")) { allowContent() }
This is useful for extending the functionality of the companion objects of third party library classes. Another advantage over Java's static members.
When to avoid companion object
Somewhat related members
When the functions/properties are not closely related but only somewhat related to a class, it is recommended that you use top-level functions/properties instead of companion object. And preferably define those functions before the class declaration in the same file as that of class:
fun getAllUsers() { }
fun getProfileFor(userId: String) { }
data class User(val id: String, val name: String)
Maintain single responsibility principle
When the functionality of the object is complicated or when the classes are big, you may want to separate them into individual classes. For example, You may need a separate class to represent a User and another class UserDao for database operations. A separate UserCredentials class for functions related to login. When you have a huge list of constants that are used in different places, you may want to group them in another separate class or file UserConstants. A different class UserSettings to represent settings. Yet another class UserFactory to create different instances of the User and so on.
That's it! Hope that helps make your code more idiomatic to Kotlin.
Why is it called "companion"?
An object declaration inside a class can be marked with the companion keyword:
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
Members of the companion object can be called by using simply the class name as the qualifier:
val instance = MyClass.create()
If you only use 'object' without 'companion', you have to do like this:
val instance = MyClass.Factory.create()
In my understanding, 'companion' means this object is companion with the outter class.
We can say that companion is same as "Static Block" like Java, But in case of Kotlin there is no Static Block concept, than companion comes into the frame.
How to define a companion block:
class Example {
companion object {
fun display(){
//place your code
}
}
}
Calling method of companion block, direct with class name
Example.Companion.display