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()
}
Related
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.
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()
As the title states, I am looking for a way to implement a final (method that cannot be overridden) in a kotlin interface.
So here is my code:
interface NewsItemState {
final fun delete(newsItem: NewsItem) {
validateCanDelete(newsItem)
deleteNewsItem(newsItem)
}
fun validateCanDelete(newsItem: NewsItem)
fun deleteNewsItem(newsItem: NewsItem)
}
And here is my use case:
I want the delete function to be final so that it cannot be
overridden in the implementations of the interface.
I want the
validateCanDelete and deleteNewsItem methods to be overridden in
the implementations of the interface.
Now, I know that this is not possible at the moment and that adding final to a method is not allowed in the interface. I also know that I can achieve this by replacing the interface with an abstract class.
However, I was wondering if there is a way of implementing the same functionality in an interface because my final method is not going to have any "state managing" logic.
While it's not possible to have final methods in interfaces, it's absolute OK to define extension methods for interface types.
interface NewsItemState {
fun validateCanDelete(newsItem: NewsItem)
fun deleteNewsItem(newsItem: NewsItem)
}
fun NewsItemState.delete(newsItem: NewsItem) {
validateCanDelete(newsItem)
deleteNewsItem(newsItem)
}
I've got an interface IMyInterface with a method
fun myMethod(thing: T){}
I also have a class
class MyClass : IMyInterface{}
What I want is that when I implement the members of the interface it automatically sets the type T to be MyClass. Is there a way of doing that?
So, instead of writing
interface IMyInterface <T>{
fun myMethod(thing: T){}
}
class MyClass: IMyInterface<MyClass>{
override fun myMethod(thing: MyClass){} // <<<-- the type is set because I explicitly set it above
}
I want to have something like this:
interface IMyInterface{
fun myMethod(thing: T){}
}
class MyClass: IMyInterface{
override fun myMethod(thing: MyClass){} // <<<-- the template type <T> of the interface is resolved by the compiler by checking what type I provided in method signature (
}
Or maybe getting a type of the class implementing an abstract class.
What you are wanting to do is not possible. You want the compiler to "Magically" figure out what the template parameter is... think about it; how would it know - there is a potentially infinite subset of IMyInterface. It is not implied in your interface that the template type <T> is even of type IMyInterface, so it could literally be any type...
Here is another angle on the problem that may make it clear why the compiler cannot do this:
// The same interface as your example, but with extra method
interface IMyInterface{
fun myMethod(thing: T){}
fun myOtherMethod(thing: T){}
}
// The same implementation as before, except the extra method is overridden with a different type than the first method
class MyClass: IMyInterface{
// the template type <T> of the interface is resolved by the compiler by
// checking what type I provided in method signature (this is what you want compiler to do)
override fun myMethod(thing: MyClass){}
// Uh oh! How does the copmpiler resolve this? We just figured out that <T> was my class.
// So this method won't compile... why not just tell entire class what <T> is
// rather than trying to make all method signatures match up so the compiler can "infer" the type???
override fun myOtherMethod(thing: MyOtherClass) {}
}
class MyOtherClass : IMyInterface {
override fun myMethod(thing: MyOtherClass) = this
override fun myOtherMethod(thing: MyOtherClass) = this
}
There is another problem which Thomas Cook's answer doesn't cover: even if this was possible, you run into major problems with subtyping in at least two ways.
Let's assume a keyword Self which means what you want and
interface IMyInterface{
fun myMethod(thing: Self): Unit
}
Problem 1: You have a val x: IMyInterface = ... What can you pass to x.myMethod? Certainly not any IMyInterface, that would defeat the purpose. But the only thing which is guaranteed to have the same concrete type as x is... x (assuming no Self-returning methods).
Problem 2: Add class MySubClass : MyClass. It must have override fun myMethod(thing: MySubClass), right? But it also has to inherit override fun myMethod(thing: MyClass) from MyClass.
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.