Property must be initialised even though type is defined in Kotlin - kotlin

I am not sure Stack overflow will like this question. I am learning Kotlin and trying to declare a basic variable without any class.
This is the simplest example.
I now understand why the compiler won't accept it, says it must be initialised. But if I put it inside the main function, then it works fine.
I saw this tutorial on W3Schools and it says you dont have to initialise the variable if you declare its type? Well I have and it still is forcing me to initialise it
https://www.w3schools.com/kotlin/kotlin_variables.php
It's a simple variable in a file no class:
/**
* Number types:
* This is the most important, and we should be able to go over it quick.
* We start from the smallest to the biggest
*/
var byteEg: Byte;
Even inside a class it doesn't work:
class Variables{
var byteEg: Byte;
}
When I try latentinit it gives an exception: 'lateinit' modifier is not allowed on properties of primitive types

What W3Schools fails to mention is that it only holds true for variables that are not top level. So inside functions like
fun someFunction() {
var byteEg: Byte
}
if you want to do it with top level declarations you can mark it as lateinit like
lateinit var byteEg: Byte

The general principle is that everything must be initialised before it's used.*
(This is in contrast to languages like C, in which uninitialised values hold random data that could be impossible, invalid, or cause an error if used; and languages like Java, which initialise everything to 0/false/null if you don't specify.)
That can happen in the declaration itself; and that's often the best place. But it's not the only option.
Local variables can be declared without an initialiser, as long as the compiler can confirm that they always get set before they're used. If not, you get a compilation error when you try to use it:
fun main() {
var byteEg: Byte
println(byteEg) // ← error ‘Variable 'byteEg' must be initialized’
}
Similarly, class properties can be declared without an initialiser, as long as a constructor or init block always sets them.
In your example, you could set byteEg in a constructor:
class Variables2 {
var byteEg: Byte
constructor(b: Byte) {
byteEg = b
}
}
Or in an init block:
class Variables {
var byteEg: Byte
init {
byteEg = 1.toByte()
}
}
But it has to be set at some point during class initialisation. (The compiler is a little stricter about properties, because of the risk of them being accessed by other threads — which doesn't apply to local variables.)
Note that this includes vals as well as vars, as long as the compiler can confirm that they always get set exactly once before they're used. (Kotlin calls this ‘deferred assignment’; in Java, it's called a ‘blank final’.)
As another answer mentions, there's an exception to this for lateinit variables, but those are a bit specialised: they can't hold primitive types such as Byte, nor nullable types such as String?, and have to be var even if the value never changes once set. They also have a small performance overhead (having to check for initialisation at each access) — and of course if you make a coding error you get an UninitializedPropertyAccessException at some point during runtime instead of a nice compile-time error. lateinit is very useful for a few specific cases, such as dependency injection, but I wouldn't recommend them for anything else.
(* In fact, there are rare corner cases that let you see a property before it's been properly initialised, involving constructors calling overridden methods or properties. (In Kotlin/JVM, you get to see Java's 0/false/null; I don't know about other platforms.) This is why it's usually recommended not to call any of a class's non-final methods or properties from its constructors or init blocks.)

Related

Importance of var keyword in Kotlin enum class constructor declaration

enum class Admin(myName:String, val id:Int, val age:Int){
ROOT_ADMIN ("Pete", 1, 55),
ACADEMIC_ADMIN("Jacob",11,56),
DEPARTMENT_ADMIN("Robin",111,50),
CLASS_ADMIN("Chris",1111,22)
To access the properties of objects of enum class Admin, when I type
Admin.CLASS_ADMIN.____
Naturally, myName to come out in the IDE auto-complete is expected. But its not happening. But id and age does come as they have val keyword associated with them.
But when I add var in front of myName, like:
enum class Admin(var myName:String, val id:Int, val age:Int)
I am now getting myName in auto-complete.
What is the importance of var keyword here?
Note: I am aware of the fact that when we declare variables with var or val keywords in constructor, it declares a property inside that class.
But how this logic relates to this situation?
This is more about Kotlin properties and less about how val/var work with enums. In fact for most of this answer, we can completely ignore the fact that we're even talking about enums, as opposed to any other Kotlin class (but I do have a note at the end on this).
For background, when you create an instance of a class in Kotlin and provide arguments to its constructor, if those arguments have var or val, Kotlin will treat them as properties. If not, it treats them as an argument to the constructor (these can be used in init blocks, for example but do not get turned into properties).
That's what is happening in your case. Kotlin treats myName as a constructor argument and effectively throws it away as you aren't using it. It does not get turned into a property. For id and age, you've specified they are val, so Kotlin turns them into read-only properties.
As for var, when Kotlin sees this it makes them into a read/write property (they can change).
Basically: Kotlin turned id and age into read-only properties and myName was defined as a constructor argument. This is why autocomplete did not offer you myName, it wasn't a property.
Some general advice: I would absolutely not declare any mutable properties on an enum (so, use val only for read-only properties). By using var, you'll get mutable read/write properties. Normally that's fine but with enum specifically there is an expectation that they do not change, ever. You are declaring a fixed set of values (an enumeration of them!) whose internal properties do not change. As a developer if I saw an enum whose internal state was mutable, it would immediately seem wrong.
Since item of enum class is acting like object in Kotlin (just for understanding), if you declare property as var of enum class, you could change the property value and it affects everywhere. This might be hard to understand. You can see below example code.
enum class Test(var a: String) {
A("a"),
B("b");
}
fun main()
{
println(Test.A.a) // a
Test.A.a = "b"
println(Test.A.a) // b
}
Usually, you might not want to declare a property as mutable for the design.

Why is a Kotlin enum property not a compile time constant?

The primary target of this question is understanding the implementation and why it is like this. A solution or workaround for it would of course also be highly appreciated...
Given this example:
enum class SomeEnum(val customProp: String) {
FOO("fooProp"),
BAR("barProp");
}
#Target(AnnotationTarget.FUNCTION)
#Retention(AnnotationRetention.SOURCE)
annotation class TheAnnotation(
val targetValue: String
)
#TheAnnotation(targetValue = SomeEnum.FOO.customProp)
fun testFun() {
}
The compilation results in the following error:
SomeEnum.kt: (14, 30): An annotation argument must be a compile-time constant
For obvious reasons, annotation values (along with others) must be compile-time constants, which makes sense in many different ways. What is unclear to me, is why customProp is not treated as a constant by the compiler.
If enums are defined as finite, closed sets of information, they should, in my understanding, only be mutable at compile-time a.k.a. "compile-time constant". For the unlikely case that enums somehow are modifiable at runtime in Kotlin, that would answer the question as well.
Addendum:
The enum value (e.g. SomeEnum.FOO) is actually treated as a compile-time constant. The proof is, that the following slightly changed snippet compiles:
enum class SomeEnum(val customProp: String) {
FOO("fooProp"),
BAR("barProp");
}
#Target(AnnotationTarget.FUNCTION)
#Retention(AnnotationRetention.SOURCE)
#MustBeDocumented
annotation class TheAnnotation(
val targetValue: SomeEnum
)
#TheAnnotation(targetValue = SomeEnum.FOO)
fun testFun() {
}
enums are defined as finite, closed sets of information, they should, in my understanding, only be mutable at compile-time
Actually, no. An enum class is just a special kind of class, that doesn't allow you to create any new instances other than the ones that you name in the declaration, plus a bunch more syntactic sugars. Therefore, like a regular class, it can have properties whose values are only known at runtime, and properties that are mutable (though this is usually a very bad idea).
For example:
enum class Foo {
A, B;
val foo = System.currentTimeMillis() // you can't know this at compile time!
}
This basically de-sugars into:
class Foo private constructor(){
val foo = System.currentTimeMillis()
companion object {
val A = Foo()
val B = Foo()
}
}
(The actual generated code has a bit more things than this, but this is enough to illustrate my point)
A and B are just two (and the only two) instances of Foo. It should be obvious that Foo.A is not a compile time constant*, let alone Foo.A.foo. You could add an init block in Foo to run arbitrary code. You could even make foo a var, allowing you to do hideous things such as:
Foo.A.foo = 1
// now every other code that uses Foo.A.foo will see "1" as its value
You might also wonder why they didn't implement a more restricted enum that doesn't allow you to do these things, and is a compile time constant, but that is a different question.
See also: The language spec
* Though you can still pass Foo.A to an annotation. To an annotation, Foo.A is a compile time constant, because all the annotation has to do, is to store the name "Foo.A", not the object that it refers to, which has to be computed at runtime.

Did I found a bug able to get a null value where Any is expected?

I learned to program with Kotlin a few months ago, and I wrote a bunch of code with it.
Recently, as I was working on a personal project, I tried something like that :
1 | sealed class Base(derivedRef: Any) {
2 |
3 | init {
4 | println("$derivedRef shouldn't be null !")
5 | }
6 |
7 | object Derived: Base(Derived)
8 | }
9 |
10| fun main() {
11| val neededToInitializeDerived = Base.Derived
12| }
At compile time, no problem: all seems to work as it should, and my IDE (Idea Intellij) doesn't highlight any part of my code in red. But, once compiled, if I try to run it, it prints a weird result :
null shouldn't be null !
After thinking a bit, it appears that derivedRef, typed as Any - and also not-null, thanks to the null safety - is, actually, null.
My theory is that when I'm passing the Derived object itself as a parameter of its own superclass constructor (and in fact the singleton instance of the Derived class, once compiled, through Derived.INSTANCE), Derived.INSTANCE isn't instantiated since the class Derived itself and its superclass Base aren't. It takes also a provisory null value, normally hidden at compile time and no more available at runtime, but that I successfully capture with this specific code snippet.
The problem is that I now have a null value instead of the normal Any one, throwing a NullPointerException as soon as I call a method needing a non-null Any value with it; I have some fun while doing impossible things using this glitch, but I think that it can be dangerous since it won't crash at runtime, letting you run your code free until the said method is called and making your program throw an unexpected error where the compiler ensures you "Don't worry, all is fine right there".
After proceeding to some tests, the bug has further consequences : I'm now able to put null values inside a MutableList<Any> :
val theForbiddenValue: Any // Let's say it's actually null
val myList = mutableListOf<Any>()
myList.add(null) // Normal, won't compile
myList.add(theForbiddenValue) // Compiles ! If I print it, I obtain "[null]" !
And to do other weird things that shouldn't happen at all, such as defining functions supposed to return Any but do not, etc. My last thought - I promise -, by making Base implements List<Any> for example, Derived will also implement it. And thus you can change the type of derivedRef from Any to List<Any>, and also obtain a null value where List<Any> is expected. This also works with every interface and/or non-final class.
So my question is, is it a real bug that I just discovered ? Or is it already known by many developers ? Or is it normal despite the appearances (I will be really surprised in that case) ??
This is about the order of construction — though it's much more subtle than most.
The most common order-of-construction issue is that in general, a constructor shouldn't refer to anything in the class that could be overridden (or changed) by a subclass.
In Java and Kotlin, a constructor always calls the superclass constructor as the very first thing it does.  (If you don't write an explicit call, the compiler inserts one for you.)  After that returns, it runs any field initialisers, and then the rest of the constructor.  So when the superclass constructor runs, none of the subclass initialisers or constructor code have been run yet.  This means that non-primitive fields will be null at that point — even if they're of a non-nullable type.
(I'm guessing that this isn't made a compile-time error because there might be circumstances in which it's perfectly fine: for example, if a subclass overrides a superclass method but doesn't refer to any fields which are overridden or set in the subclass constructor.  Note that the IDE shows a warning, such as "Accessing non-final property […] in constructor" or "Calling non-final function […] in constructor".)
What's happening in this case, however, is much less obvious, because of the combination of a sealed class and an object subclass.  As far as I can tell, the order of events is:
Because main() refers to Derived, it will construct the Derived object.
The first thing that Derived's constructor does is to call the superclass constructor, passing a reference to itself.  However, because the object hasn't yet been constructed, its reference seems to be null.  ← This is of course the cause of the bug, and ideally would give a compile-time error, or at least a warning.
The superclass constructor runs, and prints out the message you see.
The rest of the subclass constructor runs (and does nothing).  By this point, Derived gives a valid references, but by then it's too late.
The rest of the main() method runs, setting its local variable.
Here's a variation which illustrates the order a little better.  (I've moved the object outside the sealed class, though that makes no practical difference.  I've also made derivedRef a property, so we can see it afterward.)
sealed class Base(val derivedRef: Any) {
init {
println("Base.init: Derived = $Derived, derivedRef = $derivedRef")
}
}
object Derived: Base(Derived) {
init {
println("Derived.init: Derived = $Derived, derivedRef = $derivedRef")
}
}
fun main() {
println("main: Derived = $Derived, derivedRef = ${Derived.derivedRef}")
}
This prints something like:
Base.init: Derived = null, derivedRef = null
Derived.init: Derived = Derived#87aac27, derivedRef = null
main: Derived = Derived#87aac27, derivedRef = null
You can see that the Derived reference is valid once the superclass constructor has finished, even before its own constructor has finished; but of course that's too late for the property, which has already been set to null.
By the way, this doesn't happen if the object is made into a normal class: it would have to pass this when it calls the superclass constructor, but the compiler complains that "'this' is not defined in this context".
Alternatively, if the sealed class is made into a plain open class, then it compiles OK but gives a NullPointerException at runtime.
So it's the combination of sealed class and object subclass that leads to this particular issue.  Presumably the compiler can't spot that the object reference isn't valid yet (like it does for an explicit this in the case of a simple subclass).

Property references vs. lambdas for getter/setter

I need to get and set a property of another class from a method and therefore need to pass in either the property reference of lambdas for the getter and the setter:
Passing in the property reference
otherInstance::property
Passing in a lambda for the getter and one for the setter:
{otherInstance.property} // getter
{value -> otherInstance.property = value} // setter
I like the first one, because for me the code is easier to read and shorter, but my alarm bells ring when I read about it on the official documentation, because of the term "reflection". My knowledge from Java is that reflection generally isn't a good thing. Is that also valid with Kotlin? Is it valid with this case? Is one of both ways (property reference or lambdas) more performant or more safe?
By using KMutableProperty0 you would technically be exposing an object that can be used for reflection. If you want to be strict about avoiding reflection, you could use the separate function references for the getter and setter. Note that it's not necessary to pass a lambda as a function reference to a higher-order function. The compiler can interpret property references as functions if the effective signature matches. This would unfortunately mean having to pass the property reference twice. Unfortunately, the setter has to be retrieved via what is technically reflection in this case:
class Test (var x: Int)
fun foo(getter: () -> Int, setter: (Int) -> Unit) {
//...
}
val test = Test(1)
foo(test::x, test::x.setter)
// Zero reflection call:
foo(test::x) { test.x = it }
At some point you have to question how badly you want to avoid reflection, because the above code looks very messy to me. If your class takes a KMutableProperty0 reference, it is much simpler to use. As long as your receiving function isn't using the reference to introspect the code, and only calls get() or set() on it, you are not really using reflection in the ways that are suggested should be avoided.
fun foo(property: KMutableProperty0<Int>) {
//...
}
val test = Test(1)
foo(test::x)
The documentation is about Member references and reflection,
If you are referring to Property references which isn't using reflection itself,
Reflection is only referred in different section Obtaining member references from a class reference
dynamically inspect an object to see e.g. what properties and functions it contains and which annotations exist on them. This is called reflection, and it's not very performant, so avoid it unless you really need it.
Kotlin has got its own reflection library (kotlin-reflect.jar must be included in your build). When targeting the JVM, you can also use the Java reflection facilities. Note that the Kotlin reflection isn't quite feature-complete yet - in particular, you can't use it to inspect built-in classes like String.

Dlang: why are constructors not inherieted?

Is there a way to not have to repeatidly write this(parent class args) {super(parent class args);} when the arguments are exactly the same?
The code:
class Parent {
string name;
this(string name) {
this.name = name;
}
}
class Child : Parent {
}
unittest {
auto child = new Child("a name");
assert(child.name == "a name");
}
https://run.dlang.io/is/YnnezI
Gives me the compilation error:
Error: class onlineapp.Child cannot implicitly generate a default constructor when base class onlineapp.Parent is missing a default constructor
Java and C# don't inherit constructors either (unless that's changed in the last few years - I don't think C++ allowed it either until c++11), and D follows the same reasoning so you can read more by looking up things about them.
Basically though the reason is that subclasses must have their own unique state - at very least stuff like the vtable even if you don't declare any of your own variables - and thus a unique constructor is required. Otherwise you can have uninitialized members.
And if inheritance went the whole way, since Object has a this(), new AnyClass(); would compile and lead to a lot of invalid objects. (In regular D, if you declare any ctor with arguments, it disables the automatically-generated zero arg one.)
Now, D could in theory do what C++ does and auto-generate other args too... it just doesn't. Probably mostly because that is a relatively new idea in C++ and D's class system is primarily based on Java's older system.
But all that said, let me show you a trick:
this(Args...)(auto ref Args args) { super(args); }
stick that in your subclass and you basically inherit all the parent's constructors in one go. If the super doesn't compile for the given args, neither will this, so it doesn't add random things either. You can overload that with more specific versions if needed too, so it is a reasonable little substitute for a built-in language feature.