Implement a Kotlin interface in another file - kotlin

I'd like to implement some interface methods in another file, using extensions.
I have a feeling it's not possible, but I'd love to do that.
Is this possible?
Here is the idea :
MyClass.kt
class MyClass : MyInterface {
}
MyClassExtension.kt
override MyClass.MyInterface.method1() {
}
override MyClass.MyInterface.method2() {
}

That is not possible to implement the interface in the other file. There are still some possibilities.
You may split your implementation into several abstract classes, e.g. abstract class A : Interface, abstract class B : A and so on. Each class can be in its own file.
The second alternative, that does not let one implement an interface, rather split method implementations is called extension functions.
https://kotlinlang.org/docs/reference/extensions.html
Extension functions are only able to access public API of a class. Extension functions cannot implement interface methods in that case.
Use the following syntax for the declaration:
fun MyClass.method2() { ... }

Related

How does class know which implementation of an interface to take?

I have a class with a function like so:
#Component
class UpdateService(
private val storeGateway: UpdateStoreGateway,
private val loadGateway: UpdateLoadGateway,
private val updateNotify: UpdateNotify,
) : UpdateStorage {
override fun delete(key: UpdateKey) {
if (loadGateway.loadByKey(key) != null)
storeGateway.delete(key)
updateNotify.deleted()
}
}
}
UpdateStoreGateway, UpdateLoadGateway and UpdateNotify are Interfaces. Since I'm new to Kotlin I can't quite grasp how the method override fun delete(key: UpdateKey) knows which implementation of the methods to take since there is no mention of the implementation class.
It's implementing all three!
An interface requires that all implementing clases must provide method(s) with the required signature(s). (That is: having the required name, and taking the required parameter type(s).) But there are no restrictions on where that method is defined: it could be in the implementing class, or inherited from a superclass. And similarly, there are no restrictions on a method implementing more than one interface, if the signature matches.
All that matters is that users of the class know they can call the method(s) specified in all implemented interfaces; they shouldn't know or care about the details.

Make a function execute only in Kotlin interfaces?

If I have an interface, is there any easy way I can declare a function to make it a public member, but non-overridable? Meaning, it would be exclusively callable and could not be set or overridden by its descendants
interface IFoo {
fun ExecuteOnly(){
// Do Something
}
}
I read a book recently by CommonsWare where this situation was described.
and I quote it from there:
"... As a result, anything in an interface hierarchy is permanently open , until you start
implementing the interfaces in classes. If that is a problem — if you have some
function that you really want to mark as final — use abstract classes, not interfaces..."
You can define an extension function on the interface.
fun IFoo.executeOnly() {
}
It will still be possible for someone to define a member function with that name in a class implementing IFoo but the intention is quite clear. And anyway when using an object via a IFoo reference the IFoo extension will be chosen.
No, you cannot. That's not how Kotlin's interface is implemented.
You can use an abstract class instead
abstract class Foo {
fun executeOnly(){
// Do Something
}
}
Ofcourse You Can... Actually there is not much difference bw kotlin interfaces and abstract classes... simply add a body and a private modifier..
interface MyInterface {
fun triggerTakeMe(){
takeMe()
}
private fun takeMe(){
println("Taken")
}
}
class MyClass : MyInterface
fun main() {
val obj = MyClass()
obj.triggerTakeMe()
}

Singleton abstract class in Kotlin

I am implementing a library following a template method design pattern. It involves creating costly IO connection. To avoid any resource leaks, i want to enforce singleton instance on abstract class level. client just need to override the method which involves logic.
how can i do with kotlin?
abstract class SingletonConnection{
fun start(){ /* code */ }
fun connect(){ /* code */ }
abstract fun clientLogic()
}
If class A extends this, it should be singleton class. not allowed to initialise multiple times. how to do in kotlin?
Unfortunately, there is no way to enforce that only objects (singletons in Kotlin) can inherit from a certain abstract/open class or interface in Kotlin. object declaration is just syntactic sugar for a regular class with a Singleton pattern.
I know it's not much, but I guess you can achieve this to a certain degree by adding documentation, asking users to implement this class by Singletons alone.
By the way, I would use an interface instead of an abstract class for this purpose.
Instead of creating abstract class just change the code like this:-
object SingletonConnection{
fun start(){ /* code */ }
fun connect(){ /* code */ }
fun clientLogic()
}
It will provide the same implementation which you want to achieve using abstract class.
Also get the method using this code:-
SingletonConnection.start()

Is it a good idea to place the code of instance a class in a interface in Kotlin?

The Code A is from the project android/architecture-components-samples.
The author place the code of instance a class DefaultServiceLocator in the interface ServiceLocator.
In my mind , normally a interface should not include any implement code.
Is it a good idea to place the code of instance a class in a interface in Kotlin?
Code A
interface ServiceLocator {
companion object {
private val LOCK = Any()
private var instance: ServiceLocator? = null
fun instance(context: Context): ServiceLocator {
synchronized(LOCK) {
if (instance == null) {
instance = DefaultServiceLocator(
app = context.applicationContext as Application,
useInMemoryDb = false)
}
return instance!!
}
}
/**
* Allows tests to replace the default implementations.
*/
#VisibleForTesting
fun swap(locator: ServiceLocator) {
instance = locator
}
}
...
}
open class DefaultServiceLocator(val app: Application, val useInMemoryDb: Boolean) : ServiceLocator {
...
}
In my mind , normally a interface should not include any implement code.
Welcome back from hibernation ;) Yes, you could achieve the same with interface + abstract class but you can have default implementation also as part of the interface for some time now in many languages. Which way you go is up to you, but if you have only one abstract class implementing your interface then it is often handy to be able to merge this into one file for sake of ease of future maintenance.
As per kotlin interfaces documentation:
Interfaces in Kotlin can contain declarations of abstract methods, as well as method implementations. What makes them different from abstract classes is that interfaces cannot store state. They can have properties but these need to be abstract or to provide accessor implementations.
So... there's no problem in using method implementations on the interfaces. That feature might offer you extra power (if you like and need to use it).

Class delegation in Kotlin

Trait delegation is described in docs, and there are no questions. But what about class delegation?
class FrameWorkClass // Third party class we cannot modify
class MyDerivedFrameWorkClass(c:FrameWorkClass) : FrameWorkClass by c
What is the best way to achieve this without modifying FrameWorkClass? Obviously we are unable to make it implement our interface.
You can only delegate an interface to a variable that implements that interface. You cannot delegate directly to another class. As #Damian was pointing out; basically is simplified as:
interface Framework {}
class FrameWorkImpl: Framework {}
class MyDerivedFrameWorkClass(val fw: FrameWorkImpl) : Framework by fw {}
Or you can generically say:
class MyDerivedFrameWorkClass(val fw: Framework) : Framework by fw {}
to accept any implementation of the Framework interface and delegate to it, so FrameworkImpl and FrameworkHappyDays both work if they implement the Framework interface.
This is updated to current Kotlin, where trait has been renamed to interface
At the moment only traits can be delegated like this. If you have a class that you would like to delegate, I would simply take that class and extract a trait(interface) including all the methods you are interested in. Here is an example based on your code.
Imagine you have these classes:
class FrameWorkClass {
fun foo() {}
fun boo() {}
}
class MyDerivedFrameWorkClass(c:FrameWorkClass) : FrameWorkClass by c
It does not compile right? Let's say you are interested in foo()
trait FrameWorkTrait {
fun foo() {}
}
class FrameWorkClassImpl: FrameWorkTrait {
override fun foo() {}
fun boo() {}
}
class MyDerivedFrameWorkClass(c:FrameWorkTrait) : FrameWorkTrait by c
At least this is how I would do it.