1. 7
  1.  

  2. 3

    This is an important lesson and is true for all OOP languages.

    I think one of the first to make that observation was in the Gang of Four book published in 1994.

    Here is a python adaptation that also looks at possible solutions: https://python-patterns.guide/gang-of-four/composition-over-inheritance/

    1. 1

      A blog post from Oracle telling you to use composition instead of inheritance in java, and examples showing mass amounts of necessary boilerplate in order to do the thing you’re supposed to do. In comparison to inheritance, which is a single keyword.

      They’re talking the talk, but not walking the walk.

      Kotlin is the only language I’ve seen that embraces OOP and also makes composition easy, using delegation:

      interface Base {
          fun print()
      }
      
      class BaseImpl(val x: Int) : Base {
          override fun print() { print(x) }
      }
      
      class Derived(b: Base) : Base by b
      
      fun main() {
          val b = BaseImpl(10)
          Derived(b).print()
      }
      
      1. 2

        It’s worth taking note of who the author of the post is rather than where it’s posted. Joshua Bloch pretty much wrote the bible of how to write good idiomatic Java as well as writing much of the underlying code that we’re talking about here (collections stuff). Sure kotlin is cool, but it’s not like this isn’t easy to do in Java with Lombok or some other annotation processor.

        E.g. taking the example in the post:

        // see https://projectlombok.org/features/experimental/Delegate
        import lombok.experimental.Delegate; 
        
        class InstrumentedSet<E> implements Set<E> {
          @Delegate(excludes=InstrumentedSet.class)
          private final Set<E> s;
          private int addCount = 0;
        
          public boolean add(E e) {
            addCount++;
            return s.add(e);
          }
        
          public boolean addAll(Collection<? extends E> c) {
            addCount += c.size();
            return s.addAll(c);
          }
        
          public int getAddCount() {
             return addCount;
          }
        }
        

        You could argue the problems of Lombok (I’m not going to play that game today though). I think it would be difficult to argue however that switching to kotlin is easier than adding the two lines above.

        1. 2

          Assuming familiarity with and willingness to use Lombok in every Java project sounds like a big stretch to me though.

          1. 1

            Compared to switching to Kotlin?

            1. 2

              No, that was a standalone opinion. “Not in java” - “but Lombok”. I personally don’t care about Kotlin, or the comparison. I’m siding with whoever said “Not in Java” and my point was mostly re: “ not like this isn’t easy to do in Java with Lombok or some other annotation processor.”

              I don’t have a lot of experience with Lombok, but what little I had was more bad than good and so pulling it in for this is meh.

              1. 1

                Got it - your perspective makes sense to me. I put that last point alluding to the problems of Lombok for similar reasons. Overall I lean positive on it rather than negative though.

          2. 2

            If the most popular OOP language needs a third-party library to make one of the most necessary OOP patterns reasonable, while having built-in support for an antipattern, then the language is fundamentally broken.

            1. 1

              I agree, the Kotlin approach is nicer. This doesn’t make Java bad, as the approach involved isn’t hard and can easily be avoided or automated.

              The language doesn’t require lombok to achieve this. It only requires it to reduce this to a single line (like the equivalent kotlin). The article presents a one line per public method approach to the missing problem. That’s fine in my book, and isn’t going to scare away any developer worth their salt. The most used Java IDE even provides a shortcut to generate delegation methods for you.

              1. 1

                We’ll have to agree to disagree. I believe that boilerplate is just more surface area for bugs to hide in. I believe that putting code generation in IDEs as a workaround, is putting what should be in a compiler into an IDE.