1. Introduction

In Kotlin, private methods are not typically accessible outside the class. This is a useful feature for encapsulation and data hiding, but there may be situations where we need to call a private method from outside the class.

In this tutorial, we’ll explore various ways to call private methods of a class from outside the class.

2. Using a Public Method

By definition, private methods are only accessible from within the class they’re declared in.

A simple way to call a private method of a class from outside the class is to create a public method that calls the private method:

class MyPublicClass {
    private fun privateMethod(): String {
        return "This is a private method"
    }

    fun callPrivateMethod(): String {
        return privateMethod()
    }
}

In the code above, we create a public method callPrivateMethod() that simply calls privateMethod(). We can access the public method from outside the class, so in this way, we can indirectly call the private method:

@Test
fun `Makes call to private method Using public method`() {
    val obj = MyPublicClass()
        
    assertEquals("This is a private method", obj.callPrivateMethod())
}

But if we want to call our private method directly from outside its class, we’ll need to pursue other options.

3. Using Reflection

The second approach we’re going to explore involves the use of reflection. Reflection is a feature that allows us to inspect and modify the runtime behavior of a program.

To better understand this approach, let’s consider the custom class MyClass:

class MyClass {
    private fun privateMethod(): String {
        return "This is a private method"
    }
}

This is a simple class that contains a private method called privateMethod().

Now, let’s see how we can use reflection to access this private method from the MyClass class:

@Test
fun testPrivateFunctionUsingReflection() {
    val obj = MyClass()
    val privateMethod = MyClass::class.java.getDeclaredMethod("privateMethod")
    privateMethod.isAccessible = true
    val output = privateMethod.invoke(obj)

    assertEquals("This is a private method", output)
}

In the above code, we create an instance of MyClass and use reflection to access the private method privateMethod().

First, we use the getDeclaredMethod() method to obtain a reference to the method, then we set its isAccessible property to make it accessible. Finally, we invoke the private method by calling invoke() and assert that it returns the correct string.

4. Using an Inner Class

Another interesting way to call a private method from outside its class is to use a nested or inner class. An inner class is a class that is defined inside another class.

Let’s consider the MyClassWithInnerClass class that contains an inner class:

class MyClassWithInnerClass {
    private fun privateMethod(): String {
        return "This is a private method"
    }

    inner class MyInnerClass {
        fun callPrivateMethod(): String {
            return privateMethod()
        }
    }
}

In this code snippet, we define MyClassWithInnerClass with a private method privateMethod() that returns a string. Next, we define an inner class MyInnerClass with a public method callPrivateMethod() whose only job is to call the privateMethod() method.

Let’s test this approach:

@Test
fun `Makes call to private method Using Inner Class`() {
    val obj = MyClassWithInnerClass()
    val innerObj = obj.MyInnerClass()
    val output = innerObj.callPrivateMethod()

    assertEquals("This is a private method", output)
}

In this example, we create an instance of MyClassWithInnerClass and an instance of MyInnerClass. We then call the public method callPrivateMethod() to access the private method of MyClassWithInnerClass. Finally, we assert that the string that the private method returns matches our expectations.

Note that the inner class works as shown because MyInnerClass* is technically a member of *MyClassWithInnerClass, so it’s allowed to call private methods of its parent class.

5. Conclusion

In this article, we’ve explored various ways of accessing private methods of a class from outside the class. We showed different scenarios for each approach. It’s equally important that we should decide on which approach to use based on our project needs as some may be more convenient for a particular project than others.