Getter property printed on Supertype instead of injected into Kotlin

Suppose I have two classes a Base

and a Impl

that extend Base


package mypackage

open class Base
class Impl : Base()


How do I create a private property for a specific Impl

-Type (for internal use)
, with a public Base

getter injected as -Type
, to achieve polymorphism? My initial approach was like this:

class Test {
    private val myType = Impl()


However, the Kotlin compiler complains:

Error: (30, 11) Kotlin: Getter return type must be equal to property type, i.e. 'mypackage.Impl'

Basically, this is what plain Java would look like:

public class Test {
    private Impl myImpl = new Impl();

    public Base getBase() {
        return myImpl;


How can you achieve this? Did I miss something?

PS I am aware of Backing Fields and creating custom methods as a workaround for the getter, I was just curious how to approach this in an elegant Kotlin style.


source to share

2 answers

If the property is private, it will be a getter. In this case, it doesn't matter what type it will be. If you want to have a public property of the base type, you need to declare it separately:

private val _myType = Impl()

public val myType : Base
    get() = _myType




You would code this the same way you would in Java using two different properties. If you fail with Impl

never be an expert in the class. So, there are many options here:

// if you don't need Impl typed as Impl then just hold it as base
class Test1 {
    public val base: Base = Impl()

// have both with pointing one reference at the other
class Test2 {
    private val _impl = Impl()
    public val base: Base = _impl

// have both, second one is a getter (no real benefit over Test2)
class Test3 {
    private val _impl = Impl()
    public val base: Base
       get() = _impl

// use a function to do basically a cast
class Test4 {
    private val _impl = Impl()
    public fun asBase(): Base = _impl


Or don't worry about this other property, any use of Impl capture can contain it as a Base type:

class Test5 {
    public val impl: Impl = Impl()

// later
val thing: Base = Test5().impl


Maybe you want to build this with a regular interface to get a basic implementation?

open class Base {}

// a common way to get the implementation from within a class
interface Based {
    val base: Base

class ImplAbc : Base()
class ImplXyz : Base()

class TestAbc : Based {
    override val base: Base = ImplAbc()

class TestXyz : Based {
    private val _impl = ImplXyz()
    override val base: Base = _impl




All Articles