Some problem with inheritance

Hello! I have next interface:

interface MyInterface {

    fun getName(): String

    fun doSomething()

}

and I want to create abstract class with name field:

abstract class AbstractMyInterface(var name: String) : MyInterface {

    override fun getName(): String = name
    
}

but compiler says me this:

Kotlin: Platform declaration clash: The following declarations have the same JVM signature (getName()Ljava/lang/String;):
fun (): String defined in AbstractMyInterface
fun getName(): String defined in AbstractMyInterface

How can I solve this problem and how can I extends this abstract class with super constructor contains name field?

I read that I can use private field, but I want to use this field in child classes.
I read that I can use @JvmField annotation in field but in this case I have a problem with extension.

Basically, whenever you have a var or val property inside of a class, it’s just syntatic sugar for a getName, a setName and a backing field name, and so in your case you literally just need to do this:

abstract class AbstractMyInterface(override var name: String) : MyInterface {

}

or if you want custom logic in your getter:

abstract class AbstractMyInterface: MyInterface {
    override var name get() {//code goes here}
}

Also you should generally avoid functions with the name getSomething, setSomething in kotlin and use properties instead.
getSomething is something that comes from java and is used there so often that kotlin decided to add a special syntax for that, properties. So your interface should look like this instead

interface MyInterface {
    val name: String
}
2 Likes

It does not working. I can rename getName() method or name field, but I don’t want to to this. I want do this like in Java:

public interface MyInterface {
    
    String getName();
    
    void doSomething();
    
}

abstract class AbstractMyInterface implements MyInterface {
    
    protected String name;

    public AbstractMyInterface(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }
    
}

class MyInterfaceImpl extends AbstractMyInterface {

    public MyInterfaceImpl(String name) {
        super(name);
    }

     // have access to #name field

    @Override
    public void doSomething() {
        // do something
    }
    
}

All implementations need to override #getName method, but it is typically method, and I would like to have this method in abstract implementation.

Kotlin generate getter for field #name, but why this getter does not override interface method?

In that case you can try to use the JvmName annotation to resolve your signature clashes. This allows you to rename functions in the bytecode. That said, it’s likely that you have to work around a few issues if you don’t use properties and instead write your own getters/setters.

1 Like

Even though the method fun getName() and the getter of a property name are compiled to identical signatures on JVM, they are not the same as far as Kotlin itself is concerned. This means that you cannot access a property defined as val name by writing o.getName(), you cannot invoke a method defined as fun getName() by writing o.name, and you cannot override getName() with a property name or vice versa. It also means that in principle the property getter and the method can both exist, though on JVM the signature clash needs to be resolved.

That being said, I really do not understand why you want the getName method. Why not just define val name in the interface, implement it in the base class, and override the getter in the subclasses? Like this:

interface MyInterface {
    val name: String
}

abstract class AbstractMyInterface(override val name: String): MyInterface

class MyInterfaceImpl(name: String): AbstractMyInterface(name) {
    override val name: String get() {
        // do something custom
        return super.name
    }
}

If you want to make the setter available to subclasses, you can do that as well (though you do have to explicitly override it in each subclass, see KT-12996):

abstract class AbstractMyInterface(name:String): MyInterface {
    override var name = name
        protected set        
}

class MyInterfaceImpl(name: String): AbstractMyInterface(name) {
    override var name: String
        get() {
            // do something custom
            return super.name
        }
        protected set(name) {
            super.name = name
        }
}
1 Like

Answering to the original question, you can declare it this way:

interface MyInterface {
	val name: String
	
	fun doSomething()
}

abstract class AbstractMyInterface(override var name: String) : MyInterface
2 Likes

Thank you all! I chose the variant with variable in the interface.

Just to be crystal clear, you shouldn’t talk about a “variable” here, or you might misunderstand what you’re declaring when you do this:

interface MyInterface {
    val name: String
}

The syntax used in this interface defines a property, which is just an abstract read access to a String value through the name: name.

The existence of a backing field for this property really depends on the implementations of the interface. You don’t have to have a “field” or “variable” holding the data to implement the name property, just like you don’t have to have a field in Java to implement a getter method such as getName().

You only have to provide a property accessor (getter). It can be defined by accessing a value stored in a backing field, or by computing a value each time it’s called.

3 Likes