6

In Java I have these two classes :

public class Base {
    protected Long id;
    // getter setter
}
public User extends Base {
    private String name;
    private Integer age;
    public User(Long id) { this.id = id; }
    // getter setter
}

I created these two classes in Kotlin :

open class Base(var id: Long? = null)
class User(
        var id: Long? = null,
        var name: String? = null,
        var age: Int? = null
) : Base()

Now in Java I want to call the User() constructor with only the 'id' parameter :

new User(5);

This seems wrong to me, because by doing this I re-declared the "id" field in the User class.

How can I set the id field of the base class in Kotlin (like I did in Java with "this.id = id;" ?

2
  • 1
    Please edit first snippet, make User extends Base Commented Apr 13, 2018 at 7:27
  • Done. I didn't copy paste the code and forgot to add it. Commented Apr 13, 2018 at 19:20

3 Answers 3

16

First, your Kotlin code would not compile, because you would get the following error: Error:'id' hides member of supertype 'Base' and needs 'override' modifier.

Basically, the compiler would also complain that you redeclared id from Base, in User.

If you want to redeclare it, you need to first make id open in Base, and then in User, you need to use the override keyword, when redeclarding id. (also see this)

Furthermore, for the Kotlin compiler to generate overloads of the User constructor, you need to annotate your primary constructor with @JvmOverloads. Without @JvmOverloads, you wouldn't be able to use the User(id) constructor (just id as param) in Java, and would have to specify all 3 parameters.

So your code would become:

open class Base(open var id: Long? = null)

class User @JvmOverloads constructor(override var id: Long? = null,
                                     var name: String? = null,
                                     var age: Int? = null
) : Base(id)

Now, if you don't want to redeclare id in User, you can simply not use var in front of it, and instead pass it directly to Base, when calling its constructor. So basically this:

open class Base(var id: Long? = null)

class User @JvmOverloads constructor(id: Long? = null,
                                     var name: String? = null,
                                     var age: Int? = null
) : Base(id)
Sign up to request clarification or add additional context in comments.

3 Comments

I left out @JvmOverloads just to see what happens and got a compile time error. With the annotation everything works as expected. Thanks for the thorough explanation !
With pleasure! The @JvmOverloads just allows you to use the User(id) constructor in Java, instead of User(id, name, age). One annoying thing about @JvmOverloads though is that you cannot use it in Kotlin interfaces, although methods in Kotlin interfaces can have default parameters. This can yield surprises when the interface is used from Java, but they're easy to fix by overloading the method in the interface itself.
Why can't we declare the member as abstract instead of open?
1

First of all, your code will give the error: 'id' hides member of supertype 'Base' and needs 'override' modifier when you try to run it.
This is because when kotlin compiler sees var id: Long? = null it will try to create a variable with name id and type Long?. But due to inheritance it would have already had id variable in its scope.
So the compiler will complain you to either access the variable or create it and hence the above error.

Now to answer your question: How can I set the id field of the base class in Kotlin
You can do that by:

open class Base(var id: Long?=null)
class User(
        id: Long?=null,
        var name: String? = null,
        var age: Int? = null
) : Base(id)

Here in the above code, what I did is I have overridden the id variable in the child class constructor User. So this id variable can take any Long type value (that we will pass while calling the User class constructor) or null as the default value.
After that I have just passed this new value to Base class by Base(id) that is same as doing this.id = id in java.

Hope this answer is helpful.

Comments

-1

I believe it's simply a matter of passing the ID to the constructor of the superclass

open class Base(var id: Long? = null)
class User(
    var id: Long? = null,
    var name: String? = null,
    var age: Int? = null
) : Base(id)

2 Comments

Would not compile. Error would be: 'id' hides member of supertype 'Base' and needs 'override' modifier.
That should teach me to test my snippets in a scratch file. Thanks for the explanation

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.