Is it possible to pass the string data from the `S...
# getting-started
n
Is it possible to pass the string data from the
Sender
class all the way to all the classes that implements
Clickable
Copy code
interface Clickable {
    fun click(message: String)
}

class Sender {
   init {
       Clickable.click("sending from 'Sender'") // is this possible?
   }
}

class Button : Clickable {
    override fun click(message: String) = println("button $message") // receiving the message here
}
v
replace
interface Clickable
with
object Clickable
and it works
d
Or if you want it to actually be an interface for other reasons use a companion object.
n
may be I wasn’t very clear. Is it possible to pass the string data somehow from the
Sender
all the way to all the classes that implements
Clickable
d
Yes, it is. But with the code that you posted
click
is an instance method on
Clickable
, so you need an actual instance of a class that implements
Clickable
so that you can call it.
u
No, it is not. Not that straight forward. First you don't want to send to classes but to instances of that class, I guess
Second, no one is keeping track of all instances for you. You'd have to do that yourself
d
What a difference one word makes... I missed the "all" in "all the classes"...
n
Do you guys care to share some code, for the life of me I’m unable to make this works.
u
because, that is not how interfaces work
do you know java?
look up the listener pattern. you have to register every instance that should receive the data
n
Thanks, I’ll take a look at that. My knowledge of Java is basic.
u
Try to figure out the difference between classes, objects and interfaces and you will see a lot clearer
Button for example is a class.
fun click
is an instance method though, meaning it can only be called on an object of type Button. I.e. something like (in Java)
new Button()
n
Yeah, I’ll need to adapt to the way interfaces are setup with Kotlin. Coming from a Swift background, it’s quite fine to do this:
Copy code
protocol /* interface */ Clickable {
    func click(message: String)
}

class Sender {
   var delegate: Clickable?
   init() {
       delegate?.click("sending from 'Sender'") //send from here to everyone implementing the protocol (interface)
   }
}

class Button : Clickable {
    override func click(message: String) { 
        print("button $message") // receiving the message here
     }  
}
u
Well, in the kotlin example, there is no
var delegate
. With the delegate your are already moving into the right direction.
In the swift example, the delegate is never set
And it can hold one delegate, not
all
If you want to send to any one instance of Clickable, that would be mostly the same as in Swift. Except you would not call it delegate
So for a single listener it would be something like this:
Copy code
interface Clickable {
    fun click(message: String)
}

class Sender(listener: Clickable) {
   init {
       listener.click("sending from 'Sender'") // is this possible?
   }
}

class Button : Clickable {
    override fun click(message: String) = println("button $message") // receiving the message here
}

fun main(args: Array<String>) {
	var clickable = Button()
    Sender(clickable)
}
n
Thanks, this definitely works; however, it just highlighted the fact that I might be approaching it the wrong way from the beginning when trying to pass data between loosely coupled components.
u
If you can solve it in Swift, the kotlin solution won't be far 😉
Maybe an event bus is what you are looking for. On Android this one is would probably solve your problem: https://github.com/greenrobot/EventBus
n
I know, I felt when I jumped into it, it would take me a couple of minutes. Little did I know, I have been trying for a couple of hours.
Yes, an event bus would be something of interest, it’s the closest to the standard solution with Swift.
u
What exactly are you refering to with
the standard solution with Swift
n
Let me rewrite the previous code actually. I missed one part that might made a difference.
u
ok. You got me really curious
v
I think you should put here a working example in Swift which we could translate. In this area Swift and Kotlin are practically identical
n
Okay, sorry, took sometime to make sure it’s good”
Copy code
protocol /* interface */ Clickable {
    func click(message: String)
}

class Sender {
   var delegate: Clickable?
   init() {
       delegate?.click("sending from 'Sender'") //send from here to everyone implementing the protocol (interface)
   }
}

class Button : Clickable {

    val sender = Sender()

    init {
        sender.delegate = self  // set the delegate here so we'd receive the result form the calls.
}
    
    override func click(message: String) { 
        print("button $message") // receiving the message here
     }
}
I haven’t tested it out though; however, this is how delegation is used.
u
well, it should work after you move the delegate into a constructor, otherwise it is not initialized before Sender.init fires
then, except for kotline people calling delegates listeners, your swift code would almost compile as kotlin. Here is the kotlin version:
Copy code
interface Clickable {
    fun click(message: String)
}

class Sender(listener: Clickable) {
   init {
       listener.click("sending from 'Sender'") // is this possible?
   }
}

class Button : Clickable {
    val sender: Sender 
    
    init {
        sender = Sender(this)
    }
    override fun click(message: String) = println("button $message") // receiving the message here
}

fun main(args: Array<String>) {
    Button()
}
n
Alright, this works and it’s close to what I’m looking for. I’ll give this a shot in the real code and see how it’ll go 🙂
u
For a second I thought, we could have all Clickables automatically registered with the sender.
The idea was to add an init-block to the interface itself. but that is not allowed
n
Yeah, I tried something like that, but it didn’t go through 😅
I went back, rewrote my Swift example and made sure it runs without issues. It slightly different than the one I previously shared:
Copy code
protocol /* interface */ Clickable {
    func click(message: String)
}

class Sender {

   var delegate: Clickable?

   func displayMessage() {
           delegate?.click(message : "sending from 'Sender'") //send from here to everyone implementing the protocol (interface)
   }

}

class Button : Clickable {

    init() {
        let sender = Sender()
        sender.delegate = self  // delegate gets initalized in here
        sender.displayMessage()
    }

    func click(message: String) {
        print("button => \(message)") // receiving the message here
     }

}

let button = Button()
u
Almost identical in kotlin:
Copy code
interface Clickable {
    fun click(message: String)
}

class Sender() {
    
    public var listener: Clickable? = null
    
    fun displayMessage() {
        listener?.click(message = "sending from 'Sender'")
    }
    
}

class Button : Clickable {
    
    init {
        var sender = Sender()
        sender.listener = this
        sender.displayMessage()
    }
    
    override fun click(message: String) = println("button => $message")
}

fun main(args: Array<String>) {
    Button()
}
So if this is what you want, it can be done 😉
All the confusion steamed from
send from here to everyone implementing the protocol
This kind of suggested that you want the instances of clickables to automagically register for events from the sender
sending from one sender to a manually registered receiver is, as demonstarted, basically the same as in swift
n
Awesome, thanks. I’ll try it out 🙂
I can confirm that this port works great on Android. Thanks again @uli you were the hero of the day in my book 🙂
u
nawar: Welcome. Have fun with Kotlin