Kotlin property initialization - kotlin

I've created the following snippet, not anything that I would actually write in production, but just to help me understand how properties are initialized:
class C {
val a: String = run {
println("init a")
f()
}
val b: String = run {
println("init b: a=$a")
a
}
private fun f(): String {
println("f(): a=$a, b=$b")
return b
}
}
fun main() {
println(C().a)
println(C().b)
}
Note that all properties are val and String, so immutable and non-nullable. Yet the output shows that they are null.
Is the result of this code well-defined? Is there somewhere in the language spec that says that a non-nullable property can in fact be null when you access it from the wrong place?

According to the Kotlin/Core spec, the order of the execution is specified,
When a classifier type is initialized using a particular secondary constructor ctor delegated to primary constructor pctor which, in turn, is delegated to the corresponding superclass constructor sctor , the following happens, in this initialization order:
[...]
Each property initialization code as well as the initialization blocks in the class body are invoked in the order of appearance in the
class body;
[...]
but the values of the uninitialised properties are not.
If any of the properties are accessed before they are initialized w.r.t initialization order (e.g., if a method called in an initialization block accesses a property declared after the initialization block), the value of the property is unspecified. It stays unspecified even after the “proper” initialization is performed.
In other words, you will see the messages printed in the order of
init a
f(): a=null, b=null
init b: a=null
null
but the values are not guaranteed to be null.
There might be stronger guarantees in Kotlin/JVM, but there is no spec for that right now.

This is explicitly not an answer, just two small remarks/questions:
First, doesn't one of the three members a, b, or f() need to be set to a or return a value? The way it is in the OPs code, everything is null by definition as there is no non-null value anywhere. The 'call chain' is a –> f() –> b, so if we set b to a value like "start", it would look like this:
class C {
val a: String = run { f() }
val b: String = run { "start" }
private fun f(): String = b
}
fun main() {
val c = C()
println(c.a) // Output: null
println(c.b) // Output: "start"
}
Secondly, if the order is changed so that b is appearing in the code before the other two members we get a different result:
class C {
val b: String = run { "start" }
val a: String = run { f() }
private fun f(): String = b
}
fun main() {
val c = C()
println(c.a) // Output: "start"
println(c.b) // Output: "start"
}

Related

Kotlin: determine property name when reference is known

Suppose we have two classes A and B. The framework will require that A will have 0 or more properties that are of type B. The user can have a reference to an instance of B. For simplicity, assume that type B can only be declared within class A.
class A {
private val myFirstB = B(this)
private val mySecondB = B(this)
val listOfB: List<B> = mutableListOf(myFirstB, mySecondB)
}
class B(a: A) {
val myA : A = a
fun doSomething(){
// great stuff
}
}
fun testIt(){
val a = A()
val b1 = a.listOfB[0]
}
Through Kotlin reflection how can we determine the name of the property that is holding the reference to b1 within A when we only have the reference b1. We also know that B has a reference to A. Through the instance B, we can get the instance of A. Using reflection, we can get the properties of A via the declaredMemberProperties property. This can be iterated through to get the names of all the properties. However, I do not understand how to ensure that the name that is retrieved is associated with the reference b1.
As said in comments, your case looks very specific and usually reflection isn't ideal for such cases. The algorithm either has to target this very specific case, including the fact the b1 is always inside a list. Or it would have to support many different cases and "guess" where to look for b1.
Basically, the idea is to get the value of each member and compare it to the searched value:
fun main() {
val a = A()
val b1 = a.listOfB[0]
// prints: "listOfB"
println(findPropertyNameByValue(a, b1))
}
fun findPropertyNameByValue(owner: Any, value: Any): String {
return owner::class.memberProperties.first { prop ->
#Suppress("UNCHECKED_CAST")
val list = (prop as KProperty1<Any, *>).get(owner)
list is List<*> && list.any { it === value }
}.name
}
We can even get "listOfB" from the b1 alone, then the algorithm would have to iterate through members twice, again by guessing if the value is our A or not. But it is technically possible.
After some experimentation, the getter call holds the reference that is needed. Here is some possible code:
import kotlin.reflect.KClass
import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.KProperty1
fun main(){
val a = A()
val b1 = a.listOfB[0]
println(b1)
val clz: KClass<out A> = a::class
val properties: Collection<KProperty1<out A, *>> = clz.declaredMemberProperties
for(p in properties){
println(p)
println(p.name)
println(p.getter.call(a))
if (p.getter.call(a)?.equals(b1) == true){
println("This is b1")
}
}
}
class A {
val myFirstB = B(this)
val mySecondB = B(this)
val listOfB: List<B> = mutableListOf(myFirstB, mySecondB)
}
var cnt = 1
class B(a: A) {
val myA : A = a
val s = cnt++
fun doSomething(){
// great stuff
}
}
This has the following output:
ksl.B#4590c9c3
val ksl.A.listOfB: kotlin.collections.List<ksl.B>
listOfB
[ksl.B#4590c9c3, ksl.B#d62fe5b]
val ksl.A.myFirstB: ksl.B
myFirstB
ksl.B#4590c9c3
This is b1
val ksl.A.mySecondB: ksl.B
mySecondB
ksl.B#d62fe5b
As can be seen, the test of if the getter reports that it correctly finds b1

How do I run code before calling the primary constructor?

I am writing a class that contains two immutable values, which are set in the primary constructor. I would like to add a secondary constructor that takes a string and parses it to get those two values. However, I can't figure out a way to implement this in Kotlin, as the secondary constructor calls the primary constructor immediately, before parsing the string.
In java, I would call this(a,b) in one of the other constructors, but Java doesn't have primary constructors. How do I add this functionality?
class Object (a: double, b:double)
{
val a = a
val b = b
constructor(str: String) //Parsing constructor
{
//Do parsing
a = parsed_a
b = parsed_b
}
}
You can either replace your parsing constructor with a factory method:
class Object(val a: Double, val b: Double) {
companion object {
// this method invocation looks like constructor invocation
operator fun invoke(str: String): Object {
// do parsing
return Object(parsed_a, parsed_b)
}
}
}
Or make both constructors secondary:
class Object {
val a: Double
val b: Double
constructor(a: Double, b: Double) {
this.a = a
this.b = b
}
// parsing constructor
constructor(str: String) {
// do parsing
a = parsed_a
b = parsed_b
}
}
Secondary constructors are disfavored in Kotlin. Your best solution is to use a factory method. See, e.g.:
class A(val a: Int, val b: Int) {
companion object {
fun fromString(str: String): A {
val (foo, bar) = Pair(1, 2) // sub with your parsing stuff
return A(foo, bar)
}
}
}
This will lead to more readable code. Imagine a class with ten different constructors identified no way other than MyClass as opposed to many more obvious ones enabled by the factory approach: MyClass.fromString(str: String) and MyClass.fromCoordinates(coordinates: Pair<Int, Int>) and so forth.
Secondary constructors weren't even allowed in Kotlin until relatively recently.

Kotlin: How to specify a named arguent with a variable?

Suppose I have two methods:
private fun method1(a: A): A {
return a.copy(v1 = null)
}
private fun method2(a: A): A {
return a.copy(v2 = null)
}
Can I write something like:
private fun commonMethod(a: A, variableToChange: String): A {
return a.copy($variableToChange = null)
}
Another words, can I use a variable to refer to a named argument?
If I understand correctly what you are trying to archive I would recommend to pass a setter to the method e.g.
fun <A> changer (a: A, setter: (a: A) -> Unit ) {
// do stuff
setter(a)
}
Is this what you are looking for?
A possible solution for this problem (with usage of reflection) is:
inline fun <reified T : Any> copyValues(a: T, values: Map<String, Any?>): T {
val function = a::class.functions.first { it.name == "copy" }
val parameters = function.parameters
return function.callBy(
values.map { (parameterName, value) ->
parameters.first { it.name == parameterName } to value
}.toMap() + (parameters.first() to a)
) as T
}
This works with all data classes and all classes that have a custom copy function with the same semantics (as long as the parameter names are not erased while compiling). In the first step the function reference of the copy method is searched (KFunction<*>). This object has two importent properties. The parameters property and the callBy function.
With the callBy function you can execute all function references with a map for the parameters. This map must contain a reference to the receiver object.
The parameters propery contains a collection of KProperty. They are needed as keys for the callBy map. The name can be used to find the right KProperty. If a function as a parameter that is not given in the map it uses the default value if available or throws an exception.
Be aware that this solution requires the full reflection library and therefore only works with Kotlin-JVM. It also ignores typechecking for the parameters and can easily lead to runtime exceptions.
You can use it like:
data class Person (
val name: String,
val age: Int,
val foo: Boolean
)
fun main() {
var p = Person("Bob", 18, false)
println(p)
p = copyValues(p, mapOf(
"name" to "Max",
"age" to 35,
"foo" to true
))
println(p)
}
// Person(name=Name, age=15, foo=false)
// Person(name=Max, age=35, foo=true)

How to deal with nullable values in Iterator implementation in kotlin?

So I was following the Algorithms book by Sedgewick and trying to translate the implementations from Java to Kotlin and when I tried to implement one Iterator for the Bag data structure (that's essentially a one-way linked list), I got stuck with nullability issues and thread safety in Kotlin.
The implementation in java from the book is done this way:
public class Bag<Item> {
private Node first;
private class Node {
Item item;
Node next;
}
/* some methods */
private class Iterator<Item> {
private Node current = first;
public boolean hasNext() { current != null; }
public Item next() {
if (!hasNext()) throw new NoSuchElementException();
Item item = current.item;
current = current.next;
return item;
}
}
}
which I tried to implement in Kotlin like this:
class Bag<Item> : Iterable<Item> {
private inner class Node(val item: Item, val next: Node?)
private var first : Node? = null
/* Some methods */
override fun iterator() = object : Iterator<Item> {
private var current : Bag<Item>.Node? = first
override fun hasNext() : Boolean = current != null
override fun next() : Item {
if (current == null) throw NoSuchElementException()
val item = current.item
current = current.next
return item
}
}
}
But I got the following error:
Smart cast to 'Bag.Node' is impossible, because 'current' is a mutable property that could have been changed by this time
I understand this is due to race condition between checking if the variable is null and actually accessing the variable attributes, since the variable could be set to null by other threads. After some time I arrived into the following implementation:
override fun iterator() = object : Iterator<Item> {
private var current : Bag<Item>.Node? = first
override fun hasNext() : Boolean = current != null
override fun next() : Item {
current?.let {
val item = it.item
current = it.next
return item
} ?: throw NoSuchElementException()
}
}
And the compiler thought this was fine. But I still have some doubts. Which leads to my questions:
1) Is the assignment current = it.next thread safe or should I assign to the implicit it instead?
2) Is there a idiomatic Kotlin way of implementing an iterator of non-nullable type that ends with a null value? (meaning that all values in it are non-null except for the ending condition)
Is the assignment current = it.next thread safe
It is not thread safe.
Imagine a list of integers and two threads A and B who want to use iterator instance I.
1 -> 2 -> 3 -> 4 -> 5 A: item=1, next=(2)
^ A: item=1, next=(2)
I
Both threads begin to iterate. Both path inside current?.let. Both read current item (val item = it.item) and got item=1, next=(2). Then, first thread A is frozen and second thread B advances the iterator, let's say, by three items forward:
1 -> 2 -> 3 -> 4 -> 5 A: item=1, next=(2)
^ B: item=4, next=(5)
I
Now B enters let and reads next item: item=4, next=(5). Remember that A is still in his loop and it's item is item=1, next=(2). If B is now frozen and A advances one line of code (current = it.next) then things are broken: current is a shared state (as it is stored in the iterator) and, thus, B will see the change as well. On the next iteration in B it will be "thrown back" to the item #2. Nothing bad will happen and the program will not fail, but most probably that is not the behavior you need.
Even more: for the described reasons iterators are not meant to be thread-safe and every thread should have it's own, independent one. Things become more interesting with iterators that change a collection (insertions / deletions), but it's another story as it is about the collection, not about the iterator.
Should I assign to the implicit it instead?
You cannot assign to it, as it is a function parameter and it is passed by value, and, thus, cannot be changed. The compiler will ban the assignment with a message like "Val cannot be reassigned"
Is there a idiomatic Kotlin way of implementing an iterator of non-nullable type that ends with a null value?
I'd say: yes. You could potentially use sealed classes to designate different types of nodes like:
sealed class Node<out T>;
object Empty : Node<Nothing>();
data class Full<T>(val item: T, val next: Node<T>) : Node<T>();
class Bag<T>(private val first: Node<T>) : Iterable<T> {
override fun iterator(): Iterator<T> = object : Iterator<T> {
private var current = first
override fun hasNext() = current !is Empty
override fun next() = when (val c = current) {
Empty -> throw IllegalStateException()
is Full -> {
current = c.next
c.item
}
}
}
}
fun main() {
val bag = Bag(Full(1, Full(2, Full(3, Empty))))
bag.forEach(::println)
}
I was surprised to not see this method listed, which has been available since Kotlin 1.3. You can use the iterator {} helper in conjunction with yield() to easily build an iterator that handles null effectively.
For example, in a LinkedList:
class NamedLinkedListNode(
val name: String,
val next: NamedLinkedListNode?
) : Iterable<String> {
override fun iterator() = iterator {
var node: NamedLinkedListNode? = this#NamedLinkedListNode
while (node != null) {
yield(node.name)
node = node.next
}
}
}

Difference between member function and property

What is the difference?
val isFinished: Boolean
get() = actor.actions.size == 0
fun isFinished() = actor.actions.size == 0
I have no idea.
I expect them to be the same.
The first statement defines a property and the second statement defines a method.
Assume you define both in a class Foo.
val foo = Foo()
if(foo.isFinished) {} // property
if(foo.isFinished()) {} // method - see () at invocation
Under the hood, both variants call a function.
Class Property
Your first example is a class property:
class MyClass {
val isFinished: Boolean
get() = actor.actions.size == 0
}
This property defines an (optional) explicit get method, often referred to as a "getter". You could also omit the getter and do:
class MyClass {
val isFinished: Boolean = (actor.actions.size == 0) //parens not necessary
}
If omitted, as shown in the last example, the value will rather be a constant value which isn't re-calculated on each access. Both variants serve different use cases but in most cases, the latter will be sufficient.
Regardless, for a client of this class, the property can be accessed like this:
val mc = MyClass()
mc.isFinished
This shows accessing a property in Kotlin.
Class member function
Functions in Kotlin can also define functions, which can be referred to as member functions. Your second example demonstrates this feature:
class MyClass {
fun isFinished() = actor.actions.size == 0
}
Defining a member function is similar to properties with explicit getters but still different for a client, since they have to invoke a function rather than accessing a property:
val mc = MyClass()
mc.isFinished()
Side Note
Note that the shown function utilizes an expression body which is equivalent to the following block body approach:
class MyClass {
fun isFinished() {
return actor.actions.size == 0
}
}
Learn more about functions here.