Declare sepperate Getter for private and public usage - kotlin

I would like to have two getters. One for usage in the same Class and another for when the Attribute is used in other Classes. Is this possible?

Say you have a list in your class. Internally, you want to access it as mutable MutableList<T>, but externally, you want to present it as a read only view List<T>. You can simply make two properties and have one be private. Furthermore, the second property can be a getter so as not to waste additional memory.
class MyClass {
private val _myList: MutableList<String> = ArrayList()
val myList: List<String> get() = _myList
}
This is a pattern I use quite often

Related

Kotlin constructor val vs private val

If I have something like the following:
interface IRecordService {
fun doSomething () : Record
}
#MongoRepository
interface IRecordRepository : MongoRepository<Record, String> {
}
#Service
class RecordService (
private val recordRepository : IRecordRepository // or just val instead of private val
) : IRecordService
{
override fun doSomething () : Record {
// does something
}
}
Is there any difference between using private val in the RecordService constructor vs just val? I've seen both being used but couldn't tell if there was a recommended way or why.
This isn't specific to Spring or Mongo; it's just core Kotlin. There are several things going on here; I'll try to unpick them.
Consider the simpler definition:
class MyClass(i: Int)
The parens specify the primary constructor: any parameters there (such as i) are passed into the class, and are available during construction. So you could pass them up to the superclass constructor, use them in property initialisers, and/or in an init block:
class MyClass(i: Int) : MySuperclass(i) {
val someProperty = i
init {
println("i is $i")
}
}
However, they don't persist after the instance has been constructed — so you couldn't refer to them in methods, or from outside the class.
If you want to do that, you have to define a property for each parameter you want to persist. You could do that explicitly, e.g.:
class MyClass(i: Int) {
val i2 = i
}
Here every instance of MyClass has a property called i2 which is initialised to the i constructor parameter.
However, because this is a common pattern, Kotlin provides a shortcut. If you specify val or var in the primary constructor:
class MyClass(val i: Int)
then Kotlin creates a property with the same name as the parameter, and initialises it for you. So every instance of the above class has a property called i that you can refer to at any time.
By default, properties in Kotlin are public: you can access them from inside the class, from subclasses, from other classes in the same module, and from any other code that has a MyClass instance.
However, in some cases it's useful to restrict access, so you can add a visibility modifier: internal prevents code in other modules from seeing it, protected allows only subclasses to see it, and private makes it visible only inside the class itself.
So, to answer your question: without the private modifier, any code that had access to your RecordService would be able to access its recordRepository property; adding private prevents that, and means that only code within RecordService can see it.
In general, it might be a good idea to centralise all access to the recordRepository in the one class; then making it private would ensure that no other code can muck around with it. That would make it easier to see what's going on, easier to debug, and safer to work on. (However, we obviously don't know about the rest of your program, and can't advise on whether that would be a good plan in your case.)
By the way, using an I prefix for interfaces is not a convention that's used much in Kotlin (or Java). There's often little point in having an interface with only one implementation; and if you could have multiple implementations, then better to use a simple term for the interface and then more specific terms for the implementations.  (For example: the List interface with ArrayList and LinkedList classes, or Number with Int and Long.)
If you put val, it will be a constructor parameter and property. If you don't, it will be a constructor parameter (NOT property).
See Why to put val or var in kotlin class constructors
Firstly if you use val it converts this constructor parameter to property,If you do not want to hide this property (to set it) from other classes,you can use val.But if you do not want your property to be changed by other classes you should use private val instead.
Well, you can use both val and private val in your constructor there's no problem in that, it's just that with private keyword your properties wont be modified or accessed by some other class, so it basically provides some data hiding. If you talking about difference in functionality inside your RecordService class, then no there wont be any difference.

How to make a data class singleton in Kotlin?

Assume I have a data class:
data class SensorData(val name: String, val temp : Double)
I create this SensorData object from either an REST service or by internal setter method, whereas name is always populated and temp might be empty.
Further on, I need this SensorData object through several classes, thats I thought of using a singleton.
Obviously I need object keyword as described here, but how can I combine data class object ?
You can use companion object to keep a reference to your data object:
data class SensorData(val name: String, var temp : Double) {
companion object {
#Volatile
#JvmStatic
private var INSTANCE: SensorData? = null
#JvmStatic
#JvmOverloads
fun getInstance(name: String = "default", temp : Double = 0.0): SensorData = INSTANCE ?: synchronized(this) {
INSTANCE ?: SensorData(name, temp).also { INSTANCE = it }
}
}
}
And use it like this:
val name1 = SensorData.getInstance("name", 5.0).name
// Or with default values:
val name2 = SensorData.getInstance().name
I think you got the concept of a Singleton wrong:
"The singleton pattern is a software design pattern that restricts the instantiation of a class to one "single" instance"
It is not only meant to be used to make it public to all classes, but to limit the number of instances.
A data class is a class to store data, why should it be a Singleton?
Rethink your architecture to make it accessible where you need it.
Don't use a data class as a singleton. That's not what they are designed for. A better approach would be to create a wrapper object around your data class, which handles your SensorData-Object(s). This will also allow you to use multiple SensorData objects (maybe needed in future) or replace the current one with a new one if you poll the REST-Service a second time.
object SensorDataService {
var sensorData: SensorData? = null
}
data class SensorData(val name: String, val temp : Double)
In my opinion, you should rethink your architecture as data class is used to store data so why it should be a singleton? It is not only meant to be used to make it public to all classes but to limit the number of instances.

What is the benefit of having a private constructor and a use a method inside companion object to instantiate a class?

I've bumped into this code and I'm not sure why would anyone do this. Basically the author decided for making the class constructor private so that it cannot be instantiated outside the file, and added a public method to a companion object in the class that creates a new instance of this class. What is the benefit of this approach?
This is what I found:
class Foo private constructor(private val arg1: Any) {
//more code here..
companion object {
fun newFoo(arg1: Any) = Foo(arg1 = arg1)
}
}
Why is it better than this?
class Foo(private val arg1: Any) {
//more code here..
}
There are several benefits to providing a factory method instead of a public constructor, including:
It can do lots of processing before calling the construstor. (This can be important if the superclass constructor takes parameters that need to be calculated.)
It can return cached values instead of new instances where appropriate.
It can return a subclass. (This allows you to make the top class an interface, as noted in another answer.) The exact class can differ between calls, and can even be an anonymous type.
It can have a name (as noted in another answer). This is especially important if you need multiple methods taking the same parameters. (E.g. a Point object which could be constructed from rectangular or polar co-ordinates.) However, a factory method doesn't need a specific name; if you implement the invoke() method in the companion object, you can call it in exactly the same way as a constructor.
It makes it easier to change the implementation of the class without affecting its public interface.
It also has an important drawback:
It can't be used by subclass constructors.
Factory methods seem to be less used in Kotlin than Java, perhaps due to Kotlin's simpler syntax for primary constructors and properties. But they're still worth considering — especially as Kotlin companion objects can inherit.
For much deeper info, see this article, which looks at the recommendation in Effective Java and how it applies to Kotlin.
If you want to change Foo into an interface in the future the code based on the method will keep working, since you can return a concrete class which still implements Foo, unlike the constructor which no longer exists.
An example specific to android is, that Fragments should be constructed with an empty constructed, and any data you'd like to pass through to them should be put in a bundle.
We can create a static/companion function, which takes in the arguments we need for that fragment, and this method would construct the fragment using the empty constructor and pass in the data using a bundle.
There are many useful cases, for example what Kiskae described. Another good one would be to be able to "give your constructors names":
class Foo<S: Any, T: Any> private constructor(private val a: S, private val b: T) {
//more code here...
companion object {
fun <S: Any> createForPurposeX(a: S) = Foo(a = a, b = "Default value")
fun createForPurposeY() = Foo(a = 1, b = 2)
}
}
Call site:
Foo.createForPurposeX("Hey")
Foo.createForPurposeY()
Note: You should use generic types instead of Any.

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).

Why the modifier on property is the same as Getter and Setter but not Field after Java being translated into Kotlin?

Official Ref says the default Visibility Modifier is public.
But from koan data classes it can be inferred that it is private.
Is it a contradiction? What is the default Visibility Modifier of property in kotlin?
---------The above is the initial question---------------
I didn't mix property and field up. But I did have confusion on how property is accessed.
To resolve my confusion, I actually should have asked the new question in edited title.
Self-answered below.
The default visibility for properties (and functions and classes, and...) is indeed public.
The Koan is a little confusing, because the Java class has private fields with public getters.
A property can be seen as the combination of field, a getter and an optional setter. The property in the Koan has a private backing field and a public getter.
If you for example write
val age = person.age
then Kotlin will basically generate a getAge() method of the Person class, that will be called internally. This method returns the field itself.
It's also possible to add behavior to that getter. You can find more info in that in the documentation.
It's therefore not a contradiction, but a different concept.
What it the default Visibility Modifier for properties in kotlin?
It is public, as the docs say
Why are the fields not private
In this example the fields are immutable, so there are no setters defined automatically. The data class automatically has getters, and uses them, but it simplifies reading the code by not requiring them to be manually called.
Worked example
This code:
object X {
data class Example(val a: String, val b: String)
#JvmStatic
fun main(args: Array<String>) {
val e = Example("a", "b")
println(e.a)
println(e.b)
}
}
The main method of this compiles to this (with checks and metadata removed):
public static final void main(String[] args) {
X.Example e = new X.Example("a", "b");
String var2 = e.getA();
System.out.println(e.getA());
var2 = e.getB();
System.out.println(var2);
}
(Decompiled using IntelliJ IDEA)
Property encapsulates backing field by defintion. Backing field is directly assigned only when being initialized. All accesses except initialization are done through accessors.
So the private modifier on field in Java is no longer needed in Kotlin.
And the public on getter and setter in Java is placed on property(actually, still for getter and setter) in Kotlin.
Therefore the omitted modifier is public and not private.