2

I'm currently watching this video from the Google I/O 2017 and came across the by feature of Kotlin.

There is the following example to avoid to implement every single method of an interface when you actually care of only one of them.

With by implementation (from the video):

class MyListener : TransitionListener by EmptyTransitionListener {
    override fun onTransitionStart(transition: Transition) {
    }
}

object EmptyTransitionListener : TransitionListener {
    override fun onTransitionEnd(transition: Transition) {}
    override fun onTransitionResume(transition: Transition) {}
    override fun onTransitionPause(transition: Transition) {}
    override fun onTransitionCancel(transition: Transition) {}
    override fun onTransitionStart(transition: Transition) {}
}

window.sharedElementEnterTransition.addListener(MyListener())

Without by implementation (as I'm used to do):

open class EmptyTransitionListener : TransitionListener {
    override fun onTransitionEnd(transition: Transition) {}
    override fun onTransitionResume(transition: Transition) {}
    override fun onTransitionPause(transition: Transition) {}
    override fun onTransitionCancel(transition: Transition) {}
    override fun onTransitionStart(transition: Transition) {}
}

window.sharedElementEnterTransition.addListener(object: EmptyTransitionListener() {
            override fun onTransitionStart(transition: Transition) {
            }
        })

What are the advantages of one over the other?

Benjamin
  • 7,055
  • 6
  • 40
  • 60

2 Answers2

3

With by, you can reuse the same implementation for multiple class.

class MyListener : TransitionListener by EmptyTransitionListener {
    override fun onTransitionStart(transition: Transition) {
        Log.d("MyListener", "Hi from MyListener!")
    }
}

class MySecondListener : TransitionListener by EmptyTransitionListener {
    override fun onTransitionStart(transition: Transition) {
        Log.d("MySecondListener ", "Hi from MySecondListener!")
    }
}

object EmptyTransitionListener : TransitionListener {
    override fun onTransitionEnd(transition: Transition) {}
    override fun onTransitionResume(transition: Transition) {}
    override fun onTransitionPause(transition: Transition) {}
    override fun onTransitionCancel(transition: Transition) {}
    override fun onTransitionStart(transition: Transition) {}
}

window.sharedElementEnterTransition.addListener(MyListener())
Kevin Robatel
  • 8,025
  • 3
  • 44
  • 57
3

Principle: Composition > Inheritance

It simply follows the principle of "Composition over inheritance".

Composition over inheritance (or composite reuse principle) in object-oriented programming (OOP) is the principle that classes should achieve polymorphic behavior and code reuse by their composition (by containing instances of other classes that implement the desired functionality) rather than inheritance from a base or parent class. This is an often-stated principle of OOP [...].

Kotlin Delegation by

That's exactly what by is, Kotlin's keyword for applying class delegation.

The Delegation pattern has proven to be a good alternative to implementation inheritance, and Kotlin supports it natively requiring zero boilerplate code.

Delegation Pattern

Also, see https://en.wikipedia.org/wiki/Delegation_pattern:

In software engineering, the delegation pattern is an object-oriented design pattern that allows object composition to achieve the same code reuse as inheritance. [...]

Further reading

Follow this stackoverflow discussion fo further information.

s1m0nw1
  • 76,759
  • 17
  • 167
  • 196