Reputation: 2127
I have this class:
class MyClass: Fragment(), AdapterView.OnItemSelectedListener {
companion object {
fun newInstance(parent: Activity) = MyClass(parent)
}
constructor(parent: Activity) {
this.parent = parent;
}
which was giving the error, on Fragment():
Supertype initialization is impossible without primary constructor
then I followed Supertype initialization is impossible without primary constructor and changed to
class MyClass constructor(): Fragment(), AdapterView.OnItemSelectedListener {
companion object {
fun newInstance(parent: Activity) = MyClass(parent)
}
constructor(parent: Activity) {
this.parent = parent;
}
but then I got
and the Idea made me change to
constructor(parent: Activity) : this() {
this.parent = parent;
}
What does constructor
means on class MyClass constructor(): Fragment()
? Why did I have to put a this()
?
Upvotes: 0
Views: 903
Reputation: 10704
From the documentation:
A class in Kotlin can have a primary constructor and one or more secondary constructors. The primary constructor is part of the class header: it goes after the class name (and optional type parameters).
This is an example of primary constructor: class MyClass constructor()
The keyword constructor
is mandatory only if you want to specify a visibility modifier (default is public
) and/or an annotation, so all the following alternatives are equivalent:
class MyClass public constructor()
class MyClass constructor()
class MyClass()
class MyClass // parenthesis can be omitted if no argument is provided
Obviously the more concise version is preferred over the more verbose one, if that's the kind of constructor you want.
In addition to primary constructors you can also have zero, one or more secondary constructors. Secondary constructors must delegate to the primary constructor, either directly or indirectly - by calling another secondary constructor - Example: constructor(...) : this(...)
.
If your class doesn't specify any primary constructor, any secondary constructor must delegate to the super class. Example: e.g. constructor(...) : super(...)
.
If you don't specify any primary or secondary constructor, then your class will have an implicit default public constructor that takes no arguments (as in Java).
So, to answer your questions:
What does
constructor
means onclass MyClass constructor(): Fragment()
?
It declares the primary constructor, but given that you're not specifying any visibility modifiers, nor any annotations it can be omitted. The same applies to the parenthesis, hence it could be rewritten as class MyClass : Fragment()
(note the : Fragment()
bit declares your class extends Fragment
and it specifies MyClass
's default constructor should call its parent's empty constructor (more details here)
Why did I have to put a
this()
? That's mandatory for secondary constructors, as explained above.
as explained in my comment below, in the first snippet of code you are:
constructor(parent: Activity)
)class MyClass()
or class MyClass constructor()
- they're equivalent, as described above), so Kotlin will not generate a default empty primary constructor for you Fragment
and you're calling the parent's constructor as part of you class's signature. This requires a primary constructor for your class to be there, as highlighted by error you're facing: Supertype initialization is impossible without primary constructor
.One possible way is what you've done, i.e. defining both a primary and a secondary constructor. However, you'll be able to create an instance of MyClass
in 2 ways: with or without passing a parent Activity. This is roughly equivalent to the following Java code:
class MyClass extends Fragment {
private Activity parent;
public MyClass() {
super()
}
public MyClass(Activity parent) {
super()
this.parent = parent;
}
}
Probably you don't want to construct that class without a parent Activity. If that's the case, just get rid of the secondary constructor – you don't need it – and create a primary constructor that accepts whatever argument you need.
Example: class MyClass(val parent: Activity) : Fragment()
. This is a very concise way to define a primary constructor that accepts an Activity in input and assigns that argument to an instance variable called parent
; val
means parent
will be read-only (i.e. Kotlin will generate a getter but no setter), but if you need the instance variable to be mutable you can use var
instead (i.e. Kotlin will generate both a getter and a setter).
This is roughly equivalent to the following Java code:
class MyClass extends Fragment {
private Activity parent;
public MyClass(Activity parent) {
this.parent = parent;
}
}
Upvotes: 3