Hello, fellow Kotliners! Recently I’ve came across...
# announcements
j
Hello, fellow Kotliners! Recently I’ve came across a following problem. I was implementing a custom Android view, and the base View I was extending had
setEnabled
method. I’ve overridden it in my class, and used properties from the child class in this overwrite. As the properties I’ve used were unmutable and non-nullable I was startled when my app crashed with
NullPointerException
thrown in that method. Turns out it was called from the superclass constructor, and properties are initialized only after superclass constructor call. The simplified code that caused my problem looks something like: https://bit.ly/2n6xmm5 . When you run it, it throws
NullPointerException
when using seemingluynon-nullable property. Is there a pattern that would allow us to omit method calls on unitialized unmutable properties? I found two solutions to that problem, but I don’t think they’re very elegant. One using lateinit vars https://bit.ly/2nPYBBX - pretty ugly, and one using a flag https://bit.ly/2mgG4hq - pretty weird. All of the urls are shortened https://play.kotlinlang.org code snippets.
i
there's #android channel...😑
j
@Iaroslav Postovalov Thank you for letting me know, but it’s a language issue, not an Android one. I wanted to know if there’s a way in which I could check if my property was already initialized when I want to call it.
i
@Jakub Komorowski either reflection or storing nullable (or Optional, if null is valid value too)
j
@Iaroslav Postovalov In case null values are not valid, how I would go about this using reflections? The only method I know of (’`isInitialized` property) can only be used for
lateinit
properties, and, as can be seen in the snippet I provided, converting properties to those looks pretty ugly.
s
Using
isInitialized
is usually a code-smell. Use it very sparingly.. Either use nullable types
?
or use the
by lazy { .... }
(and provide the right dependencies for the code in the lazy-block to work).
j
@streetsofboston Sadly, lazy intialization doesn’t work in that case, I’m not entirely sure why: https://play.kotlinlang.org/?_ga=2.112366796.93175216.1568720306-1499155423.1536137988#eyJ2ZXJzaW9uIjoiMS4zLjExIiwicGxhdGZvcm0iOiJqYXZhIiwiYXJncyI6IiIsImpzQ29kZSI6IiIsIm5vbmVNYXJrZXJzIjp0cnVlLCJ0aGVtZSI6ImlkZWEiLCJmb2xkZWRCdXR0b24iOnRydWUsInJlYWRPbmx5IjpmYWxzZSwiY29kZSI6ImZ1biBtYWluKGFyZ3M6IEFycmF5PFN0cmluZz4pIHtcbiAgIHZhbCBkZXJpdmVkID0gRGVyaXZlZFZpZXcodHJ1ZSlcbiAgIGRlcml2ZWQuc2V0RW5hYmxlZCh0cnVlKVxufVxuXG5vcGVuIGNsYXNzIEJhc2VWaWV3KGlzRW5hYmxlZDogQm9vbGVhbikge1xuICAgIGluaXQge1xuICAgICAgICBzZXRFbmFibGVkKGlzRW5hYmxlZClcbiAgICB9XG4gICAgXG4gICAgb3BlbiBmdW4gc2V0RW5hYmxlZChpc0VuYWJsZWQ6IEJvb2xlYW4pIHtcbiAgICAgICAgcHJpbnRsbihcIkJhc2VcIilcbiAgICB9XG59XG5cbmNsYXNzIERlcml2ZWRWaWV3KGlzRW5hYmxlZDogQm9vbGVhbikgOiBCYXNlVmlldyhpc0VuYWJsZWQpIHtcbiAgICBwcml2YXRlIHZhbCBlbmFibGVkQmFja2dyb3VuZDogRHJhd2FibGUgYnkgbGF6eSB7IERyYXdhYmxlKFwiZW5hYmxlZEJhY2tncm91bmREcmF3YWJsZVwiKSB9XG4gICAgcHJpdmF0ZSB2YWwgZGlzYWJsZWRCYWNrZ3JvdW5kOiBEcmF3YWJsZSBieSBsYXp5IHsgRHJhd2FibGUoXCJkaXNhYmxlZEJhY2tncm91bmREcmF3YWJsZVwiKSB9XG4gICAgXG4gICAgb3ZlcnJpZGUgZnVuIHNldEVuYWJsZWQoaXNFbmFibGVkOiBCb29sZWFuKSB7XG4gICAgICAgIHN1cGVyLnNldEVuYWJsZWQoaXNFbmFibGVkKVxuICAgICAgICBcbiAgICBcdHNldEJhY2tncm91bmQoaWYoaXNFbmFibGVkKWVuYWJsZWRCYWNrZ3JvdW5kIGVsc2UgZGlzYWJsZWRCYWNrZ3JvdW5kKSAgICAgICAgXG4gICAgfVxuICAgIFxuICAgIHByaXZhdGUgZnVuIHNldEJhY2tncm91bmQoYmFja2dyb3VuZDogRHJhd2FibGUpIHtcbiAgICAgICBcdHByaW50bG4oXCJCYWNrZ3JvdW5kIHNldCB0byAke2JhY2tncm91bmQubmFtZX1cIilcbiAgICB9XG59XG5cbmRhdGEgY2xhc3MgRHJhd2FibGUodmFsIG5hbWU6IFN0cmluZykifQ== Nullable types are viable solution, but that creates the need to use safe calls, or non-null assertion operator in non-overriding methods.
s
Because you call
setEnabled(isEnabled)
in the constructor of the base-class
BaseView
. The sub-class
DerivedView
has not yet been instantiated at all.
j
Yes, hence my question. Of course, if I had control over the base class I could change it, but when working with existing code, such as Android view classes, I can’t really do that.
d
You can also just add
Copy code
val initialized = true

override fun setEnabled(...) {
   super.setEnabled...
   if (initialized)...