what is the best way to get `setA` to also `setB` ...
# getting-started
h
what is the best way to get
setA
to also
setB
when called, and
setB
to also
setA
when called, but not infinite loop them? One calls the other but doesn't allow itself to be called again.
Rather, I want to generalize this. I could make a boolean lock property
but this is basically synchronization, though i'm not doing a multithreaded app here
so i'm thinking maybe like a delegated class that references another function that handles it?
Maybe a custom annotation could do it for me? i don't know a lot about them
maybe it's literally just as simple as adding the
Synchronized
annotation to both setters
l
What about just a very standard function?
Copy code
fun setAB(thing: String) {
  a = thing
  b = thing
}
h
simplicity of use if written as an api or something
someone else using the code wouldn't think they had to alter B if altering A or vice versa, so wouldn't think to use the joint method
l
Do you have a more concrete example? Not sure where this is going
h
sure, exact concrete example. currently the relevant functions are annotated with synchronized, but that's a mental note as I'm not sure that's doing what I'd like it to:
Copy code
interface Temporary : Effect {
    val duration: ComparableQuantity<Time>
    var elapsed: ComparableQuantity<Time>
    val remaining: ComparableQuantity<Time> get() = duration - elapsed

    @Synchronized
    fun age(duration: ComparableQuantity<Time>) {
        elapsed += duration
        if (this is IsPeriodic)
            tick(duration)
        if (elapsed >= duration)
            end()
    }
}

interface IsPeriodic {
    val tickPeriod: ComparableQuantity<Time>
    var numTicks: Int

    fun tick(period: ComparableQuantity<Time>) = tick((period / tickPeriod).valueToInt())

    @Synchronized
    fun tick(times: Int = 1) {
        numTicks += times
        if (this is Temporary) age(tickPeriod * times)
        repeat(numTicks) { onTick() }
    }

    fun onTick()
}
l
still thinking about a cleaner solution, but meanwhile, here's a no magic just very normal boring version: https://pl.kotl.in/D9oo3JVjc TL;DR: IMO the use of
if (this is SomeOtherRandomInterface) {}
feels like a potential code smell, and I'd rather KISS for now.
h
thanks, i'll take a look
yeah, i mean, that's an easy solution to this specific situation, but it would be wonderful if we didn't need to include a combined version
that way if you implemented both interfaces, they would automatically work together properly
d
Is there a particular reason you want to implement these functions within the interfaces?
The class implementing the interfaces will know, statically, if it implements both, and has the ability to use a private function that also handles both functionalities, which can be called from
age
and
tick
I recommend using a delegate for one of the interfaces in the shared implementation. That way you don't run into common problems with inheritance. Favour composition over inheritance
1
h
Yeah composition leaves things less messy than inheritance, but I have this itch to use the latter because my mind always tells me: "this object IS this class, it doesn't HAVE it."
Also I just hate having to come up with a billion class names
I think the trouble I'm having overall though is that I have an Effect class that can have all sorts of functionalities, e.g.
Temporary
and
Periodic
, or mix and match, or all at once, and to keep things streamlined I want to pull that all out into separate interfaces. Now I'm just not sure the best way to do that.
d
Those functionalities can be modeled as attributes.
Instead of checking
effect is Periodic
you check something like effect has attribute Periodic
To solve the original problem, the implementation can use a central function to make time pass, which the other components would listen for
This seems like a nice way of doing it assuming you want to have many more of these interfaces
h
I agree. Thanks. Yeah, I can create an event based system. I appreciate it.