Boolean getter is serialized twice when annotated with #JsonProperty - kotlin

Suppose there is a class with a boolean property, its name starts with is:
class Preferrable {
var isPreferred: Boolean = true
}
It is serialized to {"preferred":true}, dropping is part.
As mentioned in this question, to prevent it, we need to specify property name explicitly, using #JsonProperty("isPreferred") annotation.
That approach works perfectly with Java. But in case of Kotlin class with annotated property serialized form contains property duplication: {"preferred":true,"isPreferred":true}.
The workaround is to apply annotation to property getter. It doesn't work for data classes and as for me, this code looks a bit too much for just keeping property name as is:
class Preferrable {
var isPreferred: Boolean = true
#JsonProperty(value = "isPreferred")
get() = field
}
What is the reason behind such behavior? Is it just a bug? Is there a simpler way to prevent is prefix dropping for Kotlin?

Booleans are handled a bit differently from other data types. You need to explicitly use #get in the annotation:
#get:JsonProperty("isPreferred")
var isPreferred: Boolean = true
Note that this does work with data classes, e.g.
data class Preferrable(
#get:JsonProperty("isPreferred")
var isPreferred: Boolean = true
)
See this question for a bit more info (and a link to where this is discussed in more detail).

Related

Kotlin: does it make sense a property with private get and public set?

I am new to Kotlin, and I have been experimenting with the language. In Kotlin in Action, it says the following:
The accessor’s visibility by default is the same as the property’s. But you can change
this if you need to, by putting a visibility modifier before the get or set keyword.
I have tried to create a property that has a private getter and a public setter, as follows:
class BackingField {
var aProperty = 1
private get
set(value) {
field = value + 1
}
}
However, IntelliJ is suggesting me to remove the private modifier before get. Is is possible to have a public property with a private getter and a public setter? If so, what are some common applications of such entity? If not, could we conclude that what is stated in the book is partially wrong?
The book is not wrong per se. Because you can actually change the visibility on both the get and set but the set can't be more visible than the get according to this question:
Private getter and public setter for a Kotlin property
Remember that books and IDEs offer recomendations and not good design based on what you do.
The set can't be more visible than the get, as other said, but then remember that properties and backing fields is just an abstraction. You can have no backing field and declare your interface setter and getter methods with the access restrictions you wish for.
Given this use case, it's obvious that you have special requirements. I.e. the data is not just set, but also incremented by 1. So your external interface would probably have another name for it as well.
Having the syntac object.field = x invoke a setter function is suspect as well, cause the syntax implies no function invocation, as in java or C/C++ structs. it can bite you horribly and make you miss the fact that the assignment invokes a setter somewhere in your code - I would consider it bad design.
The feature of properties and getters/setters works mostly if you are working with data objects and pokos (plain old kotlin objects) only. It's very good for those cases, and can save you time, but once you stray off into more complex scenarios, as you are doing, it's weakness will begin to show.
In this case you don't need a setter, because the class will have access to it privately. The getter though, is something you have to define, and perhaps give a more apropriate name, like setAndIncrement.
class BackingField {
private var aProperty = 1
fun setAProperty(value:Int) { aProperty=value+1}
private fun getAProperty():Int { return aProperty }
fun print() {println(aProperty)}
}
fun main() {
var f = BackingField()
f.print()
f.setAProperty(10)
f.print()
println(f.aProperty) // Won't compile
}

How to test if lateinit var is initialized from outside the class? - Kotlin

This SO post outlines how to test if a lateinit var has been initialized. However, in the example, the lateinit var is conveniently located within the same class.
How do you do the same thing from outside the class? This is the situation I have:
Foo.kt
class Foo {
lateinit var foo: String
}
Bar.kt
class Bar {
fun doSomething() {
val foo = Foo().foo
if (::foo.isInitialized) { // Unsupported [reference to variables aren't supported yet]
Log.i("TAG", "do something")
}
}
}
What's the workaround for this?
If this was going to work, you'd need to do
val foo = Foo()
if (foo::foo.isInitialized)
//...
The way you're doing it, you're trying to get a property reference of your local variable, which isn't a property. That's why the error says "reference to variables aren't supported yet" rather than "backing field not accessible at this point". Also, you'd be accessing the getter of the lateinit property when assigning the local variable, so it would fail if it weren't initialized yet.
But it doesn't work because of compiler limitations. You could simply add a getter
val fooReady: Boolean get() = ::foo.isInitialized
But I would say the design has very poor encapsulation if outside classes need to check whether a particular public property is initialized yet. In my opinion, any use of isInitialized is a code smell to begin with. If you need to guard calls to the getter with isInitialized, you might as well make the property nullable instead. Then you can use the familiar idioms of null checks instead of resorting to reflection, and it will work in a familiar way even for external classes that access it.
If object of another class has to make a decision based on whether or not the property is initialised, then having this property initialised - or answering whether or not it has already been initialised - is a public business capacity of your object and therefore I would recommend you to simply make it a part of your public API via public fun isFooInitialised(): Boolean function that utilises the fact that the object itself can inspect the state of its lateinit properties.

What does get() do when assigning value in Kotlin?

The code here is assigning the _showProgress to showProgress by using the get()
private val _showProgress = MutableLiveData<SingleLiveEventWrapper<Boolean>>()
override val showProgress : LiveData<SingleLiveEventWrapper<Boolean>>
get() = _showProgress
The code here is the same as above and it seems like there is no difference when running the code, it does the same job as above. What does the get() in the above code do? Is it necessary to use the get() when assigning the value?
private val _showProgress = MutableLiveData<SingleLiveEventWrapper<Boolean>>()
override val showProgress : LiveData<SingleLiveEventWrapper<Boolean>> = _showProgress
The get() method doesn't change the value — but it does change the type. (The static, compile-time type, anyway.)
The private property is a MutableLiveData field. I don't know that type, but it looks like a class or interface which wraps some data (in this case a SingleLiveEventWrapper<Boolean>), and allows it to be changed.
The public property, though, is a LiveData. That's probably a superclass or superinterface of MutableLiveData which lacks the method(s) allowing the data to be changed. The overridden getter method simply returns the value of the private property, but in doing so upcasts it to the non-mutable type.
The result is that code within the class can access the mutable field, which other code can only get a read-only view of it. So it's effectively doing some encapsulation, restricting the ability to change the field while still allowing it to be seen.
(You wouldn't need to call the getter explicitly; simply using the property syntax myObject.showProgress will call the getter for you. In Kotlin, all properties get a getter method -- and, if var a setter; you only need to override the default ones if you want different behaviour.)
Adding a bit to gidds' answer and focusing specifically on comparison with
override val showProgress : LiveData<SingleLiveEventWrapper<Boolean>> = _showProgress
If you use = ... without an explicit getter, a backing field is created and _showProgress is stored there while constructing the object. So there are two fields storing the same value. In this case this shouldn't make any difference beyond using a bit more memory, but in other cases it could:
if _showProgress was a var it could be reassigned after construction. Then if showProgress is defined with get(), accessing it will always get the current value of _showProgress, but without get() it'll get the initial one.
Similarly if _showProgress was open protected and overridden in a subclass (due to initialization order).

In Kotlin what does this get() do

Im new to Kotlin and wonder what does the get() = login_email.txt.toString() do?
Does it set email String?
get() and set(value) after a field means the declaration of a custom getter and/or setter. Here's a basic example using default values:
class Demo{
var something: String
get() = field
set(value) {
field = value;
}
constructor(something: String){
this.something = something;
}
}
These two are, however, redundant. You don't actually need them unless you're doing something custom with it. They're automatically added for vars, though that only applies to getters for vals (because they can't be changed, they don't have setters).
The line you were asking about is a custom getter.
get() // declares a custom getter
= // if you don't know how this works, see my explanation below
login_email.text.toString() // you should be familiar with this part already; gets the string value of the field
If you're not familiar with the syntax, this is the equivalent without =:
get(){
return login_email.text.toString()
}
if you have a single return, you can replace the brackets and return keyword with =. If it helps you remember, just remember the alternative to using = (a body + the return keyword)
TL;DR: it declares a custom setter that returns the value of a TextView/EditText (not sure which it is, you didn't include that in the question)
In your case, you're using a custom getter or setter to handle property data. The fields themselves don't actually contain any data, but you have getters for a different object.
Take this as an example:
class Demo(private val someObject: MyCustomObjectWithSomeData){
val text: String
get() = someObject.text
... same for other stuff. Could also have setters, if the properties are mutable
}
Here the object is private, but it could be public or internal for that matter.
Kotlin supports quite a lot with custom getters. For an instance, you can declare a field to display specific fields of a private variable. For an instance, in your case, you have the email. It doesn't need to be a variable, since you have a custom getter, and the field isn't initialized. If you change var email to a val, you can make it non-null:
val email: String
get() = login_email.text.toString()
That also helps with null-safety.
And for the error field, it's slightly more complicated. It can't be a val because you declare a custom setter, but if you add a getter, you can make it non-null:
var error: String
get() = login_error.text.toString()
set(value){
login_error.text = value;
}
Short Answer
get() is used to define a custom getter method. Anytime you access the property you are using the custom getter method
Long Answer
So before we can talk about get(), it is important that we get a proper understanding of what properties actually are.
Properties
We all know that in object oriented programming the main idea of a class is to encapsulate data and code that works on data in a single class. In a language like Java (don't worry we will get back to Kotlin soon), the data of a class is stored in private fields, we then use accessor method (getters and setters) to access the data. In Java the combination of accessor methods and a field is called a property
Now in Kotlin does things a little differently, it entirely replaces the traditional idea of defining accessor methods and fields. By using the val or var keyword Kotlin will automatically generate the corresponding field and appropriate accessor methods for us.
get()
There will come a time when either your code or someone else's code needs a more robust solution to the automatic accessor methods created by Kotlin. This is where get() and set() come into play. By using get() you are defining your own custom accessor method(getter for get()) to be used when you are accessing this property.
I would also like to point out that since val is immutable it does not allow you to define a set() method, only a get()

Why Property must be initialized when there is auto back-end field generated

I'm new to properties and moved from the java to kotlin. I'm struggling with the properties, I learned much about it but initializing the properties are confusing me, when it should be initialized or when it can work without initialization.
Let me explain it by the help of code. Below is the code which is requiring to initialize the property when the back-end field generated, before posting the code let me post the paragraph from the kotlin official website.
A backing field will be generated for a property if it uses the
default implementation of at least one of the accessors, or if a
custom accessor references it through the field identifier.
Now here is the code below.
class Employee{
var data: String // because there are default implementation of get set
// so there will be a back-end field.
}
So I have to initialize it else compilation error.
Ok I can understand it as that some one can access it so there will be no value which can produce the wrong result.
Then I move next to understand it more, so I add custom getter.
class Employee{
var data: String
get() = "default value"
}
This also generate the back-end field so compilation error to initialize it. I can understand it as that there is no initialized value so compiler complain about it.
May be compiler is not smart enough yet to check that there is value which is giving result for this property by custom getter so don't complain about initializing just return that value when required.
But there should be not a problem if any one access it then a default value is already there, then why compiler still complain?
Then I move one step more to implement custom setter too.
class Employee{
var data: String
get() = "default value"
set(value){
field = value
}
}
Still there is the back-end field because we have accessed the field so compiler generate the back-end field.
Same error, should be initialized.
Then the final stage where it works fine as below.
class Employee{
var data: String
get() = "default value"
set(value){
}
}
Now I'm not accessing field in custom getter setter so there is not a back-end field. And it works fine.
So the final question when the property should be intialized? When there is a back-end field generated?
Yes this does not compile:
class Employee{
var data: String
get() = "default value"
}
but this does:
class Employee{
val data: String
get() = "default value"
}
so maybe the compiler by stating Property must be initialized for the wrong declaration, wants from you to admit that data is something that you can not change. I say maybe.
Now the part that does compile:
class Employee{
var data: String
get() = "default value"
set(value){
}
}
This is where you explicitly admit that whatever happens I will never set a value to data, and that's why the compiler feels fine.
Just to save you from more confusion, there's a lot of explaining about Kotlin in the Internet and you may find it very difficult to get familiarized with this relatively new language, but keep in mind that everything needs to be tested by you.
I found the below code in a web page:
class User{
var firstName : String
get() = field
set(value) {field = value}
var lastName : String
get() = field
set(value) {field = value}
}
and it is presented as compilable when it's not.
You kind of answered your own question. There's no backing field when you override both getter and setter, and don't access field.
About your "compiler not being smart enough": get() function is actually RAN at runtime, so writing a lot of compiler code just to evaluate if return value is static and should be injected as default is too niche of a use case.
If your getter depends on another field which is only initialized later, this would cause a lot of confusion as to what default value should be.
Consider this code, assuming value of provider is not defined:
var data: String
get() = provider.data
What would be a default value? Do you want a null? Empty string? Maybe entire object initialization should crash? Explicit default value declaration is needed for that purpose.
That's where idea of lateinit var came to be: if You're certain you will set value before performing any get, You can use this keyword to prevent compiler errors and setting default value.
class Employee{
var data: String
get() = "default value"
}
var means there are both a getter and a setter. Because you didn't write a setter, you get the default one, which accesses the backing field. So there is a backing field, and it needs to be initialized.
But there should be not a problem if any one access it then a default value is already there, then why compiler still complain?
Because that makes the rules simpler: all properties with backing fields must be initialized. This in turn may be because in Java fields don't have to be initialized and this is a known source of bugs. I would like to say it also avoids a possible bug, because presumably you don't actually want the setter's result never to be accessible, but initializing doesn't fix that problem.
I don't see any obvious problem with changing the rules so that a field only needs to be initialized when accessed in the getter, and maybe adding a warning when only one accessor uses field. But I may be missing something, and don't see much benefit to doing so either.