Blog / October 6, 2018 / 4 mins read / By Suneet Agrawal

Object Expression in Kotlin

Sometimes we need to create an object of some class with slight modification, without explicitly declaring a new subclass for it. Java handles this case with anonymous inner classes. Kotlin uses object expression to achieve the same functionality.

We can even create an object expression for an interface or abstract class by just implementing their abstract methods. This functionality is called an anonymous interface implementation or anonymous abstract class implementation.

Let’s understand with examples

We have a class AClass having someFunction in it. We want to pass AClass object to achieve some other functionality but at the same time, we want to override the default functionality of someFunction. Ideally, this can be done by creating another class extending AClass and overriding the someFunction method and then pass the object of extending class. But we can achieve the same using an anonymous inner class in Java.

//Java code

public class AClass {
    public void someFunction(){
        System.out.println("SomeClass : some Function");
    }
}

public class UsageClass {

    public void useSomeClass(AClass someClassObj){
        someClassObj.someFunction();
    }
}

Now to use the method in UsageClass,

//Java code

UsageClass usageClass = new UsageClass();
usageClass.useSomeClass(new AClass(){
    @Override
    public void someFunction() {
        super.someFunction();
        System.out.println("UsageClass : overridden some Function");
    }
});

We created an object of AClass and passed it to useSomeClass method also we overridden the functionality of somefunction without extending the class.

The same can be achieved in Kotlin using object expression.

//Kotlin code

open class AClass {
    open fun someFunction() {
        println("SomeClass : some Function")
    }
}

class UsageClass {
    
    fun useSomeClass(someClassObj: AClass) {
        someClassObj.someFunction()
    }
}

Now to use the method in UsageClass,

//Kotlin code

val usageClass = UsageClass()
usageClass.useSomeClass(object : AClass() {
    override fun someFunction() {
        super.someFunction()
        println("UsageClass : overridden some Function")
    }
})

Same can be possible in the case of anonymous interface implementation or anonymous abstract class implementation also.

Let’s have a look.

//Java code

public abstract class AAbstractClass {
    abstract void doSomething();

    public void iAmDoingSomething() {
        System.out.println("AAbstractClass : I am doing something");
    }
}

public interface IInterface {
    void canIDoSomething();
}

public class UsageClass {

    public void useAbstractClass(AAbstractClass abstractClassObj) {

        abstractClassObj.doSomething();
        abstractClassObj.iAmDoingSomething();
    }

    public void useInterface(IInterface iInterfaceObject) {
        iInterfaceObject.canIDoSomething();
    }
}

Now to use the functions in the UsageClass,

//Java code

UsageClass usageClass = new UsageClass();
usageClass.useAbstractClass(new AAbstractClass() {
    @Override
    void doSomething() {
        System.out.println("UsageClass : I am doing something");
    }
});

usageClass.useInterface(new IInterface() {
    @Override
    public void canIDoSomething() {
        System.out.println("UsageClass : can I Do Something");
    }
});

The equivalent Kotlin code for the same using object expression will be,

//Kotlin code

abstract class AAbstractClass {
    internal abstract fun doSomething()

    fun iAmDoingSomething() {
        println("AAbstractClass : I am doing something")
    }
}

interface IInterface {
    fun canIDoSomething()
}

class UsageClass {

    fun useAbstractClass(abstractClassObj: AAbstractClass) {

        abstractClassObj.doSomething()
        abstractClassObj.iAmDoingSomething()
    }

    fun useInterface(iInterfaceObject: IInterface) {
        iInterfaceObject.canIDoSomething()
    }

    fun useSomeClass(someClassObj: AClass) {
        someClassObj.someFunction()
    }
}

To use the UsageClass,

//Kotlin code

val usageClass = UsageClass()
usageClass.useAbstractClass(object : AAbstractClass() {
    override fun doSomething() {
        println("UsageClass : I am doing something")
    }
})

usageClass.useInterface(object : IInterface {
    override fun canIDoSomething() {
        println("UsageClass : can I Do Something")
    }
})

If a supertype has a constructor, appropriate constructor parameters must be passed to it. Many supertypes may be specified as a comma-separated list after the colon :

//Kotlin code

open class BClass(val x: Int){
    open val y = 20
}
interface IInterface {
    fun canIDoSomething()
}
val bClassObj : BClass = object : BClass(10), IInterface {
    
    override val y: Int = 30

    override fun canIDoSomething() {
        println("bClassObj : can I do something")
    }

}

We can even create just an object with no nontrivial supertypes. This is called an anonymous object.

//Kotlin code

val justAnObject = object {
    var x = 10
    var y = 20
    fun sum(): Int = x + y
}

But the anonymous objects can only be used as types only in local and private declarations. If you use an anonymous object as a return type of a public function or the type of a public property, the actual type of that function or property will be the declared supertype of the anonymous object, or Any if you didn’t declare any supertype. In that case, the members added in the anonymous object will not be accessible.

//Kotlin code

class CClass {
    // Private function, so the return type is 
    // the anonymous object type
    private fun privateFunction() = object {
        val x: String = "x"
    }

    // Public function, so the return type is Any
    fun publicFunction() = object {
        val x: String = "x"
    }

    fun main() {
        val x1 = privateFunction().x        // Works fine
        val x2 = publicFunction().x        // ERROR: 
                                        //Unresolved reference 'x'
    }
}

One last thing, unlike Java we can access non-final variables also inside an object expression.

//Java code

int value = 0;
usageClass.useInterface(new IInterface() {
    @Override
    public void canIDoSomething() {
        value++;       // Error
                      
// variable 'value' is access from withing inner class, needs to be declared final.
    }
});

In Kotlin, this works fine

//Kotlin code

var value = 0

usageClass.useInterface(object : IInterface {
    override fun canIDoSomething() {
        value++           // works fine
    }
})
Comments