4
votes

Neither of the two pages, the one on Interfaces, nor the one on Visibility Modifiers provides an example of the syntax I am after, so I ask.

I have an interface like so:

package bookyard.contracts;

public interface IAuthenticationManager<T> {
    fun authenticateUser(userName: String, password : String,
                            appId: String, appSecret : String) : OperationResult<T>;
}

And I am writing an implementation for it but neither of the three below listed syntaxes work. Each time, the compiler reports the following error:

  1. 'authenticateUser' overrides nothing

  2. Class 'DatabaseAuthenticationManager' must be declared abstract or implement abstract member public abstract fun authenticateUser(userName: String, password: String, appId: String, appSecret: String): OperationResult defined in bookyard.contracts.IAuthenticationManager

package bookyard.server.util

import bookyard.contracts.IAuthenticationManager;

public class DatabaseAuthenticationManager :  IAuthenticationManager<User> {

    /* override public fun authenticateUser(userName : String?,
                                password : String?,
                                appId : String?,
                                appSecret : String?) : OperationResult<User> {
    }

    public override fun authenticateUser(userName : String?,
                                password : String?,
                                appId : String?,
                                appSecret : String?) : OperationResult<User> {
    }

    public fun authenticateUser(userName : String?,
                                password : String?,
                                appId : String?,
                                appSecret : String?) : OperationResult<User> {
    } */
}
2
You're using String? instead of String as the data type for a lot of the parameters. They aren't interchangeable. You can make your interface use nullable Strings and it won't complain about the signature.byxor

2 Answers

3
votes

Your problem is that you're using nullable Strings when attempting to implement the interface.

From Kotlin's documentation about null-safety...

In Kotlin, the type system distinguishes between references that can hold null (nullable references) and those that can not (non-null references).

String? (nullable String) and String are considered to be different types by Kotlin. Therefore the compiler thinks that you haven't implemented the method.

Your options...

You have 2 options:

  1. Update your interface to use nullable parameters (by adding ? to the end of each type).

  2. Update your implementation to use non-nullable parameters (String).

I think option 2 is slightly cleaner since it won't break any other existing implementations of the interface.

Example (for option 2):

The interface stays unchanged.

Here's the new implementation...

package bookyard.server.util

import bookyard.contracts.IAuthenticationManager

class DatabaseAuthenticationManager : IAuthenticationManager<User> {

    override fun authenticateUser(userName : String,
                                  password : String,
                                  appId : String,
                                  appSecret : String) : OperationResult<User> {
        // Your implementation...
    }
}

You can see that all I've done is change each parameter from String? to String.

Notes:

  • Classes/fields/interfaces are public by default, the public keyword is unnecessary.

  • Kotlin has semi-colon inference so you don't need to add semi-colons yourself. There are rare cases where you will actually need to, but the compiler will warn you in advance.

1
votes

Every overridden method needs to conform to the interface declared parameter nullability. In other words the correct way to implement the interface would be:

class DatabaseAuthenticationManager :  IAuthenticationManager<User> {
    override fun authenticateUser(userName: String, password: String, appId: String, appSecret: String): OperationResult<User> {
        ...
    }
}