hi, is there any way to initialize a immutable pro...
# announcements
n
hi, is there any way to initialize a immutable property in a data class in the constructor? In non-data class I've seen examples for the
lazy
keyword that might can help for me, but I don't know how I could use it in a data class. I want something like in C++ how we define a
const
instance variable in the constructor. Here is an example what I would like to do:
Copy code
data class MyClass(val property: String) {   # <-- mutable
	init {
		this.property = property.capitalize()
	}
}

instance = MyClass("test")
instance.property # Test
instance.property = "test2" # error, immutable variable
but unfortunately the compiler says
Val cannot be reassigned
when I set
this.property
. Do you know how I could use immutable instance variable here?
k
Well
val
means immutable, I think you're looking for
var
.
n
sorry, I made a mistake. immutable.
(edited)
k
No you can't initialize a parameter
val
, it is already initalized by the main constructor itself.
If you want to do some preprocessing on data class parameters you can do something like this:
Copy code
data class MyClass(property: String) {
    val property = property.capitalize()
}
n
unfortunately it raises the following error if I don't use
val
or
var
before the constructor argument:
Data class primary constructor must have only property (val / var) parameters
k
Ah right that's unfortunate.
a
@nucc IMO a data class shouldn't have any code in it, I'd go with a top level factory method
đź‘Ť 1
e
why don’t you do the capitalization in a factory method instead?
k
The problem with that is that the
copy
function leaks the constructor, so I'd be able to do
MyClassFactory("test").copy(property = "test")
to get a "broken" instance.
n
I need to amend the data and if I put the logic to each class where I want to initialize a
MyClass
object then I need to copy the logic everywhere. Or I should create a factory class, but I don't really want to create a
MyClassFactory
just to do some modification on a string.
k
I really which there was a
@NoCopy
annotation to avoid stuff like this.
You can make the constructor private and name the factory
MyClass
, Kotlin allows it.
But the issue I mentioned remains.
n
hmm. okay, thanks
e
what if you add a property to your data class that returns the capitalized string?
n
yeah, I was thinking on the same.
k
That works in this case but breaks equality and such when the preprocessing isn't an injective function like
Math.abs
.
We've had this exact discussion before in this Slack 🙂.
Actually doesn't work for
capitalize
either, consider
MyClass("test") == MyClass("Test")
.
n
yes, it's true, fortunately my transformation is injective.
you're right, I used it as an example only