Hoinzey

Javascript. Kotlin. Android. Java

Kotlin: Class delegation using "by"

In my composition over inheritance post I gave an example using a Forwarding set. The forwarding set is useful but it also contains a huge amount of boilerplate. In Kotlin however we can achieve the same affect using the by keyword.


Below is the code from the previous post and how you could achieve the same in far less code using Kotlin.


Old forwarding set
Kotlin delegation
                    
    public class ForwardingSet<E> implements Set<E> {

        private final Set<E> set; // <-- Composition
    
        public ForwardingSet(Set<E> set) {
            this.set = set;
        }
    
        @Override
        public int size() { return set.size(); }
    
        @Override
        public boolean isEmpty() { return set.isEmpty(); }
    
        @Override
        public boolean contains(Object o) { return set.contains(o); }
    
        @Override
        public Iterator<E> iterator() { return set.iterator(); }
    
        @Override
        public Object[] toArray() { return set.toArray(); }
    
        @Override
        public <T> T[] toArray(T[] a) { return set.toArray(a); }
    
        @Override
        public boolean add(E e) { return set.add(e); }
    
        @Override
        public boolean remove(Object o) { return set.remove(o); }
    
        @Override
        public boolean containsAll(Collection<?> c) { return set.containsAll(c); }
    
        @Override
        public boolean addAll(Collection<? extends E> c) { return set.addAll(c); }
    
        @Override
        public boolean retainAll(Collection<?> c) { return set.retainAll(c); }
    
        @Override
        public boolean removeAll(Collection<?> c) { return set.removeAll(c); }
    
        @Override
        public void clear() { set.clear(); }
                                        
    
        public class ComposedCountedSet<E> extends ForwardingSet<E>{

            private int addCount = 0;
        
            public ComposedCountedSet(Set<E> set) {
                super(set);
            }
        
            @Override
            public boolean add(E e) {
                addCount++;
                return super.add(e);
            }
        
            @Override
            public boolean addAll(Collection<? extends E> c) {
                addCount += c.size();
                return super.addAll(c);
            }
        
            public int getAddCount() {
                return addCount;
            }
        }
                                        

That is a substantial difference. Keep in mind that another java class would still need to implement that forward set and override the methods as needed, which is what Kotlin manages to do without us needing to write another class.

Resources

This post was written after reading Chapter 4 in Kotlin in action by Dmitry Jemerov & Svetlana Isakova. I would highly recommend this book from my reading so far and to clarify - I am in no way associated with it.