Blog / March 3, 2020 / 5 mins read / By Suneet Agrawal

Destructuring Declarations in Kotlin

We all know about three classes Any, Unit and Nothing in Kotlin which have their own functionality and use cases but we usually confuse between the differences among them and when to use what.

Let try to understand what are these, when to use what and how these are different from one another.

Any

Any is an open class and by default the superclass for all the classes, whether we define it explicitly or not. This is similar to the Object class in Java which is the superclass for each and every class.

/**
 * The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass.
 */
public open class Any {

    public open operator fun equals(other: Any?): Boolean
    public open fun hashCode(): Int
    public open fun toString(): String
}

Any has 3 functions

  • equals
  • hashCode
  • toString

All three functions are well-known functions which can be overridden in any class.

equals

/**
 * Indicates whether some other object is "equal to" this one. Implementations must fulfil the following
 * requirements:
 *
 * * Reflexive: for any non-null value `x`, `x.equals(x)` should return true.
 * * Symmetric: for any non-null values `x` and `y`, `x.equals(y)` should return true if and only if `y.equals(x)` returns true.
 * * Transitive:  for any non-null values `x`, `y`, and `z`, if `x.equals(y)` returns true and `y.equals(z)` returns true, then `x.equals(z)` should return true.
 * * Consistent:  for any non-null values `x` and `y`, multiple invocations of `x.equals(y)` consistently return true or consistently return false, provided no information used in `equals` comparisons on the objects is modified.
 * * Never equal to null: for any non-null value `x`, `x.equals(null)` should return false.
 */
public open operator fun equals(other: Any?): Boolean

equals functions check if the object is equal to the object passed in parameter. There are different criteria on which equals function checks the equality but we can override this function in any class.

hashCode

/**
 * Returns a hash code value for the object.  The general contract of `hashCode` is:
 *
 * * Whenever it is invoked on the same object more than once, the `hashCode` method must consistently return the same integer, provided no information used in `equals` comparisons on the object is modified.
 * * If two objects are equal according to the `equals()` method, then calling the `hashCode` method on each of the two objects must produce the same integer result.
 */
public open fun hashCode(): Int

hashCode returns a unique integer for each and every object of that class. This function is also open and we can override it according to our use case.

toString

/**
 * Returns a string representation of the object.
 */
public open fun toString(): String

This is the most commonly overridden function which is used to represent the object in string form. This is again open and we can override it according to the use case.

We can even create an object of Any class and use any of the above functions.

val any: Any = Any()

any.equals(Any())
any.hashCode()
any.toString()

Unit

Unit class is an object class which means it a singleton class having only one object.

/**
 * The type with only one value: the `Unit` object. This type corresponds to the `void` type in Java.
 */
public object Unit {
    override fun toString() = "kotlin.Unit"
}

Unit is exactly equivalent to the void type in Java. We can explicitly add Unit as the return type for functions returning void.

fun doSomething() {
    //do something here
}

fun doSomething() : Unit {
    //do something here
}

Both the above functions are absolutely the same but for the second one, there will a warning stating

Redundant 'Unit' return type

We can’t extend Unit class.

object AnotherUnit : Unit {
}

class AnotherUnit : Unit {
}

//both above will have Error: Compilation error
"Cannot inherit from a Singleton"

We can’t even create an object of it.

val unit: Unit = Unit()
unit.toString()

//error: Compilation error in first line

"Expression 'Unit' of type 'Unit' cannot be invoked as a function.
The funciton 'invoke()' is not found"

Nothing

Nothing is used to represent a value which will never exist.

This is has a private constructor and also cannot be extended.

/**
 * Nothing has no instances. You can use Nothing to represent "a value that never exists": for example,
 * if a function has the return type of Nothing, it means that it never returns (always throws an exception).
 */
public class Nothing private constructor()

It is used to define a function return type which is going to throw an exception every time.

fun iWillAlwaysThrowException() =  throw Exception("Unnecessary Exception")

//The ebove function will show a Error: compilation error

'Nothing' return type needs to be specified explicitely

and the correct syntax will be

fun iWillAlwaysThrowException() : Nothing =  throw Exception("Unnecessary Exception")

The best example of Nothing is in TODO function.

/**
 * Always throws [NotImplementedError] stating that operation is not implemented.
 */

@kotlin.internal.InlineOnly
public inline fun TODO(): Nothing = throw NotImplementedError()

/**
 * Always throws [NotImplementedError] stating that operation is not implemented.
 *
 * @param reason a string explaining why the implementation is missing.
 */
@kotlin.internal.InlineOnly
public inline fun TODO(reason: String): Nothing = throw NotImplementedError("An operation is not implemented: $reason")

Differences between Any, Unit and Nothing

Any

  • Any is by default the superclass of all the classes and has 3 functions: equals, hashCode and toString. This is equal to Object class in Java.
  • We can create an object of Any class directly or even override these functions in any other class.

Unit

  • Unit class is a singleton class, we can’t extend or even create an object of it.
  • Unit class in equal to void type in Java.
  • The superclass of Unit is Any and it has overridden toString method.

Nothing

  • Nothing is non-open (final class) which can’t be extended and its constructor is also private that means we can’t create the object also.
  • This is usually used to represent the return type of function which will always throw an exception.
  • The superclass of Nothing is Any.
Comments