Subclass var initialization step and OOP structure design - oop

The abstract super class Parent has abstract method extract(Int), getting the value a from primary constructor, and submit it to that method extract(a).
abstract class Parent ( val a : Int ) {
abstract fun extract ( i : Int )
init {
// call overriden extract(Int)
extract ( a )
}
}
The sub class Child defines the method extract(Int), sending the value b to the Parent's constructor, then the super class Parent calling extract(Int) to set that value to Child's variable x.
class Child ( b : Int ) : Parent ( b ) {
// initialize x variable to -1
var x : Int = -1
override fun extract ( i : Int ) {
// set x to given int
x = i
}
}
Testing:
println ( Child ( 10 ).x )
And got:
-1
Now, try adding init{} of the sub class Child
init {
x = -2
}
Testing again:
println ( Child ( 10 ).x )
And got:
-2
Seemingly, the init{} of sub class Child is done after the super class Parent's construction.
Should the extract(Int) be overridden ann called by all sub classes, rather than by the super class?

I am not sure what you mean by "super class Child", but it seems you may be confused of the order of derived classes. Here is a really good example that shows the order. It has a code snippet that you can run on the site.

Generally speaking this kind of initializer interaction is frowned upon, since the exact order of operations, while well defined, is often counter-intuitive.
Specifically, what I believe is happening here, might be more clear using the more verbose explicit-constructor syntax in kotlin. You're code is an abbreviated version of this (note, this is legal kotlin):
abstract class Parent {
val a: Int
constructor(a: Int){
this.a = a
extract(a)
}
abstract fun extract ( i : Int )
}
class Child: Parent {
var x : Int
constructor(b: Int): Parent(b) {
//super.constructor(b) fires here
// initialize x variable to -1
x = -1
}
override fun extract (i : Int) {
// set x to given int
x = i
}
}
thus, as I hope is now a little more clear, a pseudo-call-trace is like this:
enter Child.constructor(10)
enter Parent.constructor(10)
assign 10 to this#Parent.a
enter this.extract(10) => V-Table resolves Child.extract()
assign 10 to this#Child.x
extract returns
Parent.constructor returns
assign -1 to this#Child.x this is probably your point of confusion
Child.constructor returns
What you can do
Generally speaking, when you encounter confusing initialization flows, the answer on the JVM is to formalize the complex initialization in another method, rather than in more init or constructors.
In kotlin the simplest way to do this --and a strategy used by many many libraries-- is to create a static factory method.
abstract class Parent(val a: Int) {
//...
}
class Child private constructor(var x: Int): Parent(x) {
companion object {
fun makeChild(unextracted: Int) {
val extracted = extract(unextracted)
return Child(extracted)
}
// a first good step is to make `extract` referentially transparent
// aka pure
// IE all of its function is provided in its return type
fun extract (i : Int): Int {
return i //do appropriate transforms.
//note, if you need multiple return values here, consider Pairs or Triples.
}
}
}
Note, kotlin provides some syntax sugar for this, you can override the invoke operator:
class Child { companion object { operator fun invoke(x: Int) { ... } } }
which means that instead of makeChild (eg Child.makeChild(10)) to call your factory function you to use ~constructor syntax (Child(10)).
Even more generally, if you find yourself running into this problem under an IOC container which, for whatever reason, must use initializer flow, I would encourage you to refactor your IOC consumers to use old-fashioned java factories. I'll need more details to elaborate here.

Related

Is there a way to mock the invocation of a secondary constructor of a Kotlin data class using mockk

From the documentation of mockk.io regarding the mocking capabilities of constructors I can see the following:
class MockCls(private val a: Int = 0) {
constructor(x: String) : this(x.toInt())
fun add(b: Int) = a + b
}
mockkConstructor(MockCls::class)
every { constructedWith<MockCls>().add(1) } returns 2
As far as I understood it is possible to mock the construction of an object and get a result for an executed method.
What I would like to have is e.g. the following
data class MyDataClass(val first: String) {
constructor(anotherDataClass: AnotherDataClass) : this(
first = anotherDataClass.second
)
}
data class AnotherDataClass(val second: String)
mockkConstructor(MyDataClass::class)
every { constructedWith<MyDataClass>() } returns mockk<MyDataClass>
or
every { anyConstructed<MockCls>() } returns mockk<MyDataClass>
In the end, I want to bypass the construction and directly return a constructed mock and not first execute a method and return the result.
Avoiding constructor execution while mocking not currently (<=1.12.0) possible by design (https://github.com/mockk/mockk/issues/515)
If you really want to capture instance while doing constructor mocking, you can get away with this:
val myMockedInstance: MyClass = MockKGateway.implementation().constructorMockFactory.mockPlaceholder(
MyClass::class,
args = arrayOf<Matcher<*>>(
EqMatcher(dummyParamOfMine)
) as Array<Matcher<*>>
)

ExceptionInInitializerError "Parameter specified as non-null is null" with abstract class

I need to calculate the hash of hard-coded images.
abstract class ImageData {
protected abstract val master: List<String>
val data: Iterable<HexString> = master.map { s -> hex(s) }
val hash: Int by lazy {
master.fold(0) { hash, s ->
31 * hash + s.hashCode()
}
}
}
Example image.
object FooImageData : ImageData() {
override val master = listOf(
"424d3684030000000000..."
// ...
)
}
Exception:
java.lang.ExceptionInInitializerError
at ....updateGraphics(Graphics.kt:162)
...
Caused by: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter $this$collectionSizeOrDefault
at kotlin.collections.CollectionsKt__IterablesKt.collectionSizeOrDefault(Iterables.kt)
at ....ImageData.<init>(ImageData.kt:17)
at ....FooImageData.<init>(FooImageData.kt:3)
at ....FooImageData.<clinit>(FooImageData.kt:3)
at ....updateGraphics(Graphics.kt:162)
at ....updateGraphics(Graphics.kt:162) is:
private suspend fun updateGraphics(...) {
val hash = (FooImageData.hash * 31 + BarImageData.hash)
Removing the lazy does not remove the problem.
All research suggests the ordering of the parameters can be an issue but that seems to be not the case here - or is it?
Using:
abstract class ImageData {
abstract val master: List<String>
// Yes I know the `get()` is unnecessary but for some weird reason that causes `hash` to crash.
val data: Iterable<HexString> get() = master.map { s -> hex(s) }
val hash: Int by lazy {
master.fold(0) { hash, s ->
31 * hash + s.hashCode()
}
}
}
seems to solve the problem - no idea why.
Kotlin version Latest stable (1.3)
Target JVM version: 1.6
I think the key difference is get() on the data property, in conjunction with the fact that master is abstract. When this base class is constructed (which is before the subclass is created, since the subclass's constructor has to call the superclass's constructor before anything else), the base class initialises all its members. Your original code had this line:
val data: Iterable<HexString> = master.map { s -> hex(s) }
This gets the value of master which, at this point, is null, as the concrete subclass hasn't been created yet so can't yet override the property.
In your updated snippet, you have this:
val data: Iterable<HexString> get() = master.map { s -> hex(s) }
The data property now doesn't need to be initialized (using the value of master) during initialisation of the abstract base class. Instead, when the data property is called at runtime, the get function will be executed. By that time the concrete subclass has been constructed and can provide a proper value for master.
There's more detail on this in the documentation, where it says:
When designing a base class, you should therefore avoid using open
members in the constructors, property initializers, and init blocks.
(The master property is abstract, which means it's open.)

What's the purpose of `val` property with `final` modifier?

Recently IntelliJ suggested to add final to one of a val properties. This particular property was initialized in init {} block. I've tried to find out what is the semantics of final val construct and when should I use it, but Kotlin is all about immutability and how val is equivalent of final in Java and so results were so noisy, that I couldn't find anything.
Example:
final val id: Int // `final` suggested by IDE
init { id = 1 }
What is the meaning and possible usages of similar property? By applying final what limitations it implies beyond immutability, which is already known? Does it have anything to do with inheritance or external access?
IntelliJ stopped sugessting final if property is private.
The example as it is should not suggest adding final as it does nothing in this case. The only place where adding final makes sense in Kotlin is when overriding members. By adding final to an overridden property (or method), you're preventing subclasses from further overriding it.
For example:
open class A {
open val x: Int = 0
}
open class B : A() {
final override val x: Int = 25
}
class C : B() {
override val x: Int = 56 // Error: `x` in `B` is final and cannot be overridden
}
The final keyword isn't really applicable if:
the class you're in isn't open,
the property isn't open,
the property is private.

How can I assign a value to KMutableProperty parameter?

In a method I would like to receive KMutableProperty as parameter and assign a value to it.
Another question is what is the correct way of passing a parameter into such a method.
Basically I would like to have something like that:
class MyBinder {
...
fun bind(property: KMutableProperty<Int>): Unit {
property.set(internalIntValue)
}
}
And then call it in another class
myBinder.bind(this::intProperty)
Kotlin 1.0 does not allow the this::intProperty syntax, but this is being worked currently and will be available soon as a part of the early access preview of 1.1 (issue, KEEP proposal).
With this in mind, I'd consider doing what you're describing in another way, for example making bind accept a lambda which sets the property:
class MyBinder {
fun bind(setProperty: (Int) -> Unit) {
setProperty(internalIntValue)
}
}
...
myBinder.bind { intProperty = it }
Anyway, to answer your question about setting the value of KMutableProperty: to set the value of some property or, technically speaking, to invoke the property setter, you should know its arity, or the number of parameters that property (and its getter/setter) accepts. Properties declared in a file do not accept any parameters, member properties and extension properties require one parameter (the receiver instance), while member properties which are also extensions take two parameters. These kinds of properties are represented by the following subtypes of KMutableProperty respectively: KMutableProperty0, KMutableProperty1, KMutableProperty2 -- the number means the arity and their generic type parameters mean the types of receivers. Each of these property types has a set method with the corresponding parameters. Some examples:
fun setValue(property: KMutableProperty0<Int>, value: Int) {
property.set(value)
}
fun setValue(property: KMutableProperty1<SomeType, Int>, instance: SomeType, value: Int) {
property.set(instance, value)
}
Note that there's no set (or get) method in the abstract KMutableProperty interface precisely because it's impossible to declare it, not knowing the number of required receiver parameters.
Additionally to Alexander's answer, you can try something like this:
import kotlin.reflect.KMutableProperty
class Binder {
val internalIntValue = 10
fun bind(self: Any, aProperty: KMutableProperty<Int>) {
aProperty.setter.call(self, internalIntValue)
}
}
class Foo {
var bar = 1
fun changeBar() {
Binder().bind(this, Foo::bar)
}
}
fun main(args: Array<String>) {
val foo = Foo()
assert(1 == foo.bar)
foo.changeBar()
assert(10 == foo.bar)
}
A more robust/safe way to do the same thing:
fun <T> bind(self: T, aProperty: KMutableProperty1<T, Int>) {
aProperty.set(self, internalIntValue)
}
My thanks to Alexander. His answer gave me the previous idea.

Extension fields in Kotlin

It's easy to write extension methods in Kotlin:
class A { }
class B {
fun A.newFunction() { ... }
}
But is there some way to create extension variable? Like:
class B {
var A.someCounter: Int = 0
}
You can create an extension property with overridden getter and setter:
var A.someProperty: Int
get() = /* return something */
set(value) { /* do something */ }
But you cannot create an extension property with a backing field because you cannot add a field to an existing class.
No - the documentation explains this:
Extensions do not actually modify classes they extend. By defining an extension, you do not insert new members into a class, but merely make new functions callable with the dot-notation on instances of this class.
and
Note that, since extensions do not actually insert members into classes, there’s no efficient way for an extension property to have a backing field. This is why initializers are not allowed for extension properties. Their behavior can only be defined by explicitly providing getters/setters.
Thinking about extension functions/properties as just syntactic sugar for calling a static function and passing in a value hopefully makes this clear.
However, if you really, really want to do something like this...
As stated above regarding efficiency, an additional backing field added directly to the class is the best way to store data non-derivable from existing non-private members from the class. However, if you don't control the implementation of the class and are dead-set on creating a new property that can store new data, it can be done in a way that is not abysmally inefficient by using separate external tables. Use a separate map that keys on object instances of this class with values that map directly to the value you want to add then define an extension getter and/or setter for this property which uses your external table to store the data associated with each instance.
val externalMap = mutableMapOf<ExistingClass, Int>()
var ExistingClass.newExtensionProperty : Int
get() = externalMap[this] ?: 0
set(value:Int) { externalMap[this] = value }
The additional map lookups will cost you - and you need to consider memory leaks, or using appropriately GC-aware types, but it does work.
There's no way to add extension properties with backing fields to classes, because extensions do not actually modify a class.
You can only define an extension property with custom getter (and setter for var) or a delegated property.
However, if you need to define an extension property which would behave as if it had a backing field, delegated properties come in handy.
The idea is to create a property delegate that would store the object-to-value mapping:
using the identity, not equals()/hashCode(), to actually store values for each object, like IdentityHashMap does;
not preventing the key objects from being garbage collected (using weak references), like WeakHashMap does.
Unfortunately, there is no WeakIdentityHashMap in JDK, so you have to implement your own (or take a complete implementation).
Then, based on this mapping you can create a delegate class satisfying the property delegates requirements. Here's an example non-thread-safe implementation:
class FieldProperty<R, T : Any>(
val initializer: (R) -> T = { throw IllegalStateException("Not initialized.") }
) {
private val map = WeakIdentityHashMap<R, T>()
operator fun getValue(thisRef: R, property: KProperty<*>): T =
map[thisRef] ?: setValue(thisRef, property, initializer(thisRef))
operator fun setValue(thisRef: R, property: KProperty<*>, value: T): T {
map[thisRef] = value
return value
}
}
Usage example:
var Int.tag: String by FieldProperty { "$it" }
fun main(args: Array<String>) {
val x = 0
println(x.tag) // 0
val z = 1
println(z.tag) // 1
x.tag = "my tag"
z.tag = x.tag
println(z.tag) // my tag
}
When defined inside a class, the mapping can be stored independently for instances of the class or in a shared delegate object:
private val bATag = FieldProperty<Int, String> { "$it" }
class B() {
var A.someCounter: Int by FieldProperty { 0 } // independent for each instance of B
var A.tag: String by bATag // shared between the instances, but usable only inside B
}
Also, please note that identity is not guaranteed for Java's primitive types due to boxing.
And I suspect the performance of this solution to be significantly worse than that of regular fields, most probably close to normal Map, but that needs further testing.
For nullable properties support and thread-safe implementation please refer to here.
You can't add a field, but you can add a property, that delegates to other properties/methods of the object to implement its accessor(s). For example suppose you want to add a secondsSinceEpoch property to the java.util.Date class, you can write
var Date.secondsSinceEpoch: Long
get() = this.time / 1000
set(value) {
this.time = value * 1000
}
If you are extending View you can do it quite easily like this...
This is example how I create some my custom class Event property in EditText class extension:
Define id for key :
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="EditTextEventOnClearTagKey" type="id" />
</resources>
Define one reusable extension like this:
fun <T : Any> View.tagProperty(#IdRes key: Int, onCreate: () -> T): T {
#Suppress("UNCHECKED_CAST")
var value = getTag(key) as? T
if (value.isNull) {
value = onCreate()
setTag(key, value)
}
return value!!
}
Use it in wherever View extension you need:
val EditText.eventClear get() = tagProperty(R.id.EditTextEventOnClearTagKey) { event<Unit>() }