Exit Full View

Kotlin's Scope Functions with and apply are Dangerous

Kotlin has a clever trick, which changes the meaning of this.

Inside the with block this no longer refers to SalesRep, but to Customer :

  1. class SalesRep {
  2. fun endOfYearBonus() {
  3. for ( customer in customers ) {
  4. with ( customer ) {
  5. if ( isHappy() ) {
  6. awardBonus()
  7. }
  8. }
  9. }
  10. }
  11. fun awardBonus() {
  12. ...
  13. }
  14. }

If we only look at the endOfYearBonus method, we can guess that isHappy() is a method of Customer and awardBonus() is a method of SalesRep. But we can't be sure. This makes our code hard to read.

We could have made this explicit, by using this.isHappy() and this@SalesRep.awardBonus(), but we tend not to. The main reason for using with is to avoid clutter!

Now imagine that months/years later, we add a new method :

  1. class Customer {
  2. fun awardBonus() {
  3. // Do something
  4. }
  5. }

Our old code, which has not changed, is wrong!

Our Sales Reps get no bonuses! The Kotlin compiler checks each implied this sequentially. It first looks for Customer.awardBonus(), and only if that fails, it then looks for SalesRep.awardBous().

If both implied receivers have a matching method, Kotlin does NOT report an error, or even a warning. (Kotlin version 1.4.10).

Hopefully it will in the future, but for now, I consider this a severe issue; a ticking time bomb.

I've never seen one blow up, but we shouldn't accept such flaws in our programming language.