Abstract fun invoke() not implemented - kotlin

I've created a View and I encountered a problem with my interface for Buttons ClickListener.
Interface looks like this
interface CustomButtonsClickListener : () -> Unit {
fun onPlusClick(view: View, button: ImageButton)
fun onMinusClick(view: View, button: ImageButton)
}
It is implemented by the method:
fun setCustomButtonsClickListeners(clickListener: CustomButtonsClickListener) {
binding.addButton.setOnClickListener {
clickListener.onPlusClick(this, binding.addButton)
}
binding.minusButton.setOnClickListener {
clickListener.onMinusClick(this, binding.minusButton)
}
}
This is how it look like "outside"
view.setCustomButtonsClickListeners(object : CustomButtonsClickListener {
override fun onPlusClick(view: View, button: ImageButton) {
}
override fun onMinusClick(view: View, button: ImageButton) {
}
})
The Problem:
I am getting error on object saying:
Object is not abstract and does not implement abstract member public abstract fun invoke()...
What is the method invoke() and how should I implement it? I would rather do it inside the View class so I don't have to do it while using the View somewhere in the app.

This looks like confusion over syntax.  The line:
interface CustomButtonsClickListener : () -> Unit {
creates an interface which extends () -> Unit (and goes on to add two methods to it).
() -> Unit is the type of a function which takes no parameters and returns nothing useful.  You don't often need to know that function's name (as the lambda syntax hides it), but this is one of those corner cases where you find out that it's called… invoke()!
(It's described in the documentation.)
So you're defining an interface with three methods: one inherited from the parent interface, and the other two declared here.
So of course, when you try to implement the interface but implement only two of those three methods, the compiler complains that you've forgotten the third.
I guess you just want an interface with only your two new methods, so you can simply declare it with:
interface CustomButtonsClickListener {

Related

Delegate one interface to multiple implementations

Could a class delegate an interface to multiple implementations with a few lines? Given this interface:
interface Foo {
fun doA()
fun doB()
}
The following class would compile for a single delegate:
class FooImpl(delegate: Foo): Foo by delegate
Although useless, it generates java bytecode for what is should do: delegate Foo -> Foo.
Could this be possible for a list of delegates as well? Such that it delegates Foo -> List<Foo>. Like:
class FooImpl(delegates: List<Foo>): Foo by delegates
Right now, our codebase is filled with classes such as:
class FooImpl(private val delegates: List<Foo>): Foo {
override fun doA() { delegates.forEach { it.doA() }
override fun doB() { delegates.forEach { it.doB() }
}
It feels like busy work and it's unnecessarily error prone, plus it creates unneeded work for the dev writing the code and the dev reviewing the code. I'm aware it can become complex for return values, but that will never be the case. In the current code, there's always a set of an interface, 2 actual implementations and a root implementation filled with doA() { delegates.forEach { it.doA() } .
Could this be simplified using Kotlin?

Calling lifecycle.addObserver from a Kotlin abstract class

I have an abstract class that implements DefaultLifecycleObserver. I'd like to call lifecycle.addObserver(this) from the init block, but it says "Leaking 'this' in constructor of non-final class MyAbstractClass".
My code:
abstract class MyAbstractClass(protected val activity: AppCompatActivity) : DefaultLifecycleObserver {
init {
activity.lifecycle.addObserver(this)
}
.
.
.
}
I can move this line of code to the init block of each final class that extends this abstract class, but I don't like the idea, especially because I want to guarantee that each new class that will extend MyAbstractClass in the future will call it as well.
Is there a better place to call this without creating a leak?
I suppose you could post your call so it only happens after the object is fully instantiated:
abstract class MyAbstractClass(protected val activity: AppCompatActivity) : DefaultLifecycleObserver {
init {
Handler(Looper.getMainLooper()).post {
activity.lifecycle.addObserver(this)
}
}
}
Or it might be less surprising to create an extension function you can tack onto your constructor calls. Then you can explicitly start the observation immediately. You'd have to make activity public, though. By defining it in an extension like this, your subclasses can call this and return themselves so you can chain it to constructor calls.
fun <T: MyAbstractClass> T.alsoBegin(): T {
activity.lifecycle.addObserver(this)
return this
}
val foo = SomeImplementation(myActivity).alsoBegin()

Final methods in kotlin interfaces

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

Dealing with immutability in a GUI-based application

I have a GUI based application (Kotlin) that consists of a list of Notes to the left (it shows the note's title) and the selected Note's edition screen to the right.
When the users modify the title in the edition screen, the list item must show the new title.
In a mutable world, I'd do something like this:
interface Note {
fun title(): String
fun content(): String
fun setTitle(newTitle: String)
fun setContent(newTitle: String)
fun addListener(l: Listener)
}
class NoteListItem(n: Note) : Listener {
init {
n.addListener(this)
}
override fun onChange() { //from Listener
repaint();
}
fun repaint() {
//code
}
}
class NoteEditionScreen(n: Note) {
fun onTitleTextChanged(newTitle: String) {
n.setTitle(newTitle)
}
//...
}
Inside Note.setTitle method, listeners are notified.
Both "screens" have the same instance of Note, so changes are propagated.
However, with immutability:
interface Note {
fun title()
fun content()
fun title(newTitle: String) : Note
fun content(newContent: String) : Note
}
the method Note.title(String) returns a new instance of Note instead of changing the state.
In that case, how can I "notify" to the NoteListItem the title has changed?
Obviously, those two concepts don't go together nicely here.
The essence of the elements on your UI is: they allow for changes. The user doesn't know (or care) if the underlying object is immutable or not. He wants to change that title.
Thus, there are two options for you:
give up on your Node being immutable
introduce an abstraction layer that is used by your UI
In other words: you can add a mutable NodeContainer that is used for displaying immutable node objects on your UI.
Now you have to balance between having the advantages of keeping your Node class immutable and the disadvantages of adding mutable wrapper thingy around the Node class. But that is your decision; depending on your context.

Wrong "this" being used in nested closures

I'm trying to keep this minimal, but let me know if I'm being too minimal.
Suppose you have a class hierarchy like this, designed for generating HTML (inspired by the Kotlin tutorial; semi-pseudocode follows):
class Tag {
protected val children = arrayListOf<Tag>()
operator fun String.unaryPlus() = children.add(Text(this))
}
class TagWithChildren : Tag() {
fun head(init: Head.() -> Unit) = initializeTag(Head(), init)
fun script(init: Script.() -> Unit) = initializeTag(Script(), init)
fun <T : Tag> initializeTag(tag: T, init: T.() -> Unit): T {
tag.init()
children.add(tag)
return tag
}
}
class Head : TagWithChildren()
class Script : Tag()
class Text(val str: Text) : Tag()
Notice that Head has head and script methods while Script doesn't.
Now you can construct a template that looks like this:
head {
script {
+"alert('hi');"
}
}
Which works great! However, if the block passed to script tries to call methods that aren't available on Script, it can call the method on Head instead. For example,
head {
script {
script {
+"alert('hi');"
}
}
}
not only isn't a compile error, it's actually equivalent to
head {
script {
}
script {
+"alert('hi');"
}
}
which is super confusing, from a template author's perspective.
Is there any way to prevent method lookups from traveling up the scope like that? I only want it to look at the innermost scope.
UPDATE 11/24/2016:
Kotlin 1.1-M03 has introduced scope control, which I believe solves exactly this problem. https://blog.jetbrains.com/kotlin/2016/11/kotlin-1-1-m03-is-here/
The current behavior is intentional. Code in a lambda has access to receivers of all enclosing scopes. It is possible that a future version of Kotlin will add a modifier that will restrict a lambda with receiver to calling methods on that receiver only and not the enclosing scopes, but in the current version there's no way to change that behavior.
As a workaround, I can have it fail at runtime if I change the classes to look like this:
open class Tag {
operator fun String.unaryPlus()
// pulled up from TagWithChildren, call protected method
fun head(init: Head.() -> Unit) = addChild(Head())
fun script(init: Script.() -> Unit) = addChild(Head())
// throws in Tag
open protected fun addChild(t: Tag) = throw IllegalArgumentException()
}
class TagWithChildren : Tag() {
// overridden to not throw in subclass
protected override fun addChild(t: Tag) = children.add(t)
}
This way, every Tag has the builder methods (solving the scoping problem), but actually calling them may result in a runtime failure.