y
08/02/2023, 5:51 AMinit
block. I am now getting a warning that such properties must be "initialized, finalized or abstract" and that this behavior is deprecated (soon to be a hard error)
1. is this a new Kotlin change?
2. what is the idiomatic way to solve this, since some of these initialization are a little complex? a dedicated private fun
initializer for each initialized value?Youssef Shoaib [MOD]
08/02/2023, 5:55 AMinit
block before the `override val`sy
08/02/2023, 5:59 AMclass Bar : Baz() {
override val foo: Foo // warning: property must be initialized, etc.
init {
foo = something()
}
}
however
class Bar : Baz() {
init {
foo = something() // error: variable cannot be initialized before declaration
}
override val foo: Foo
}
y
08/02/2023, 6:19 AMChris Lee
08/02/2023, 6:20 AMy
08/02/2023, 6:21 AMy
08/02/2023, 6:22 AMChris Lee
08/02/2023, 6:24 AMy
08/02/2023, 6:27 AMy
08/02/2023, 6:27 AMChris Lee
08/02/2023, 6:28 AMxoangon
08/02/2023, 6:31 AMval
and in the second, the variable is not yet declared.
For the first case, I think you may have a confusion with the pipeline of a class initialisation in Kotlin. The constructor arguments are those arguments needed to be called to create an instance of the class. The properties outside the constructor and the init
block are called afterwards, once you have an instance of the class.
For instance, the following code:
class Bar(val constructorArgument: String) {
val afterConstructedProperty: String
init {
afterConstructedProperty = "stringValue"
}
}
Has this equivalent code in Java:xoangon
08/02/2023, 6:34 AMconstructorArgument
is an argument of the Java constructor public Bar(@NotNull String _constructorArgument_)
, while constructedProperty
is declared and assigned after the instance is initialised using the super()
cally
08/02/2023, 6:40 AMxoangon
08/02/2023, 6:42 AMinit
block
I wonder now if there are cases where this is different. Anyway, it feels confusing to have the initialisation of a constructor argument in the init
block of the classChris Lee
08/02/2023, 6:47 AMpublic abstract class Baz {
public abstract val x : Int
}
public class Bar : Baz() {
override val x: Int
init {
x = 5
}
}
public class Bar1 : Baz() {
override val x: Int
init {
x = something()
}
private fun something() : Int = 5
}
y
08/02/2023, 6:49 AMsealed class Baz {
abstract val name: String
class Bar : Baz() {
override val name
init {
name = "foobar!"
}
}
}
Chris Lee
08/02/2023, 6:55 AMThis property must either have a type annotation, be initialized or be delegated
For similar patterns I tend to only use constructor parameters; in the case where you want to insulate construction from the caller use a companion object:
public sealed class Baz3(public open val name : String) {
public class Bar3 private constructor(public override val name: String) : Baz3(name) {
public companion object {
public fun create(): Bar3 {
return Bar3("abc")
}
}
}
}
y
08/02/2023, 7:12 AMy
08/02/2023, 7:13 AMChris Lee
08/02/2023, 7:14 AMKlitos Kyriacou
08/02/2023, 9:42 AMsealed class Baz {
abstract val name: String
class Bar : Baz() {
override val name: String
init {
name = "foobar!"
}
}
}
y
08/02/2023, 9:42 AMKlitos Kyriacou
08/02/2023, 9:57 AMKlitos Kyriacou
08/02/2023, 9:57 AMKlitos Kyriacou
08/02/2023, 9:57 AM: String
to the override val declarationy
08/02/2023, 10:01 AMy
08/02/2023, 10:01 AMKlitos Kyriacou
08/02/2023, 10:20 AM