ClaudiuB
05/29/2020, 7:19 PMval
-ness, a sort of lazy by
? Confused of the heuristics here. Should I make it var
if I plan on it changing? adapter
doesn't change, the onActionPerformed
can
val onActionPerformed: ((String, Any) -> Unit)?
get() {
return adapter?.onActionPerformed
}
Adam Powell
05/29/2020, 7:22 PMval
only means that there is no set
operation available.ClaudiuB
05/29/2020, 7:27 PMval
with java final
from primitivesCasey Brooks
05/29/2020, 7:40 PMval
, it only has a getter function, no setter. And since the property is computed, there actually wonât be a field generated for that property. Itâs literally just a getter function.ClaudiuB
05/29/2020, 8:02 PMval x = y.z()
vs
val x: Z
get() {
return y.z()
}
Are they the same thing? val x = y.z()
feels to me like final Object
assigned "on site" only, relying on some other y
provided earlier in the constructor in the chainClaudiuB
05/29/2020, 8:03 PMClaudiuB
05/29/2020, 8:04 PMval
can't be reassigned if I write it like val x = y.z()
and that implies some finality. Here y might not change, Z could. So my real problem is that yes I'm not reassigning the value, but the value does change đClaudiuB
05/29/2020, 8:08 PMget() {}
wrapper provides me with a runtime evaluation of it that val x = y.z()
won't?Casey Brooks
05/29/2020, 8:08 PMval x = y.z()
, youâre telling the compiler âwhen this class is created, compute y.z()
and assign it to `x`â. There is no get()
, so the compiler treats it like a final Object
from Java, creates a backing field, and stores that value in that field.
When you use get()
, youâre telling the compiler âcompute this value when itâs requested`, and being the smart compiler it is, it will omit the backing field since youâre declaring you want to re-compute it with each callClaudiuB
05/29/2020, 8:09 PMClaudiuB
05/29/2020, 8:09 PMval can't be reassigned
might not be a fully correct statementClaudiuB
05/29/2020, 8:10 PMval x = y.z()
is more const
-ishClaudiuB
05/29/2020, 8:12 PMassigned
=> change
ClaudiuB
05/29/2020, 8:13 PMval x = y.z()
if a getter would mean val x = get{ y.z()}
, and many others might tooClaudiuB
05/29/2020, 8:15 PMCasey Brooks
05/29/2020, 8:17 PMfun foo() = y.z()
being different than val foo = y.z()
. But the main thing to keep in mind is that properties should be treated like getters and setters, and declaring get()
or set()
on them allows you to add custom computation to those getters and setters. Assignment still means what it normally does, setting some data somewhere, but whether its a field or something else is just an implementation detailClaudiuB
05/29/2020, 8:18 PMif(return not wrapped in getter)
{
x
} else
{
y
}
Or maybe as a suggestion, have const val
work as you said and normal val
provide uniform functionality with get{}
ClaudiuB
05/29/2020, 8:19 PMval x = y.z()
, if treated as a get()
, is not the assignment of a lambda that is called. Like you are not setting the getter, but you can, kinda, if you wrap it in get(){.. }
ClaudiuB
05/29/2020, 8:21 PMval x = y.z()
is a getter of a sort of const val temp = y.z()
evaluated before x
, instead of () -> y.z()
ClaudiuB
05/29/2020, 8:21 PMClaudiuB
05/29/2020, 8:23 PMClaudiuB
05/29/2020, 8:28 PMval x: Z
get() {
return y.z()
}
instead of val x = y.z()
because they are not the same thing, my y.z()
might change even though y
won't.ClaudiuB
05/29/2020, 8:35 PMClaudiuB
05/29/2020, 8:36 PMClaudiuB
05/29/2020, 8:37 PMy.z()
ClaudiuB
05/29/2020, 9:10 PMusually
to your statement of them being = get + set
, because they act like fields if val x = y.z()
doesn't indeed call y.z()
and instead is the evaluation of it.
It looks like val/var
act as a Pair of immutable functions Pair<Function<Unit,Type>,<Function<Type,Uni>t>
, yet with more than merely setting the getter/setter functions and why val can't be reassigned
triggered some brain melt.
Kotlin wrap what you give as assignments and getter like
get() {
return initialVal ?:
getter()
}
, so you get different functionality if you wrap in getter. This sparks some more questions, why isn't assignment in val
not allowed outside of initialVal
if a val is not a final object and merely a var without the ability to set a setter.ClaudiuB
05/29/2020, 9:11 PMval
logic contrasted to var
abit oddClaudiuB
05/29/2020, 9:12 PMval
having specific logic and rules. Sparked some great paths, love using Kotlin btw â¤ď¸ClaudiuB
05/29/2020, 9:16 PMWe can define custom accessors for a property. If we define a custom getter, it will be called every time we access the property (this allows us to implement a computed property). Here's an example of a custom getter:Right. I went for oh if it is indeed only a getter, than assignment inline would mean assignment of the getter
Casey Brooks
05/29/2020, 9:41 PMval
without an explicit get()
function is effectively equivalent to a final
field in Java. Thus, you can set it a single time, at the object construction time, either through property initialization (val x = y.z()
) or in the classâs init { }
block.
class Foo {
// initialized in the class body
val x: String = y.z()
}
class Foo {
// initialized in the class init block
val x: String
init {
x = y.z()
}
}
Because itâs val
and not var
, you are declaring that consumers can only ever access that property (Foo().x
), but that they can never set a value to it. You can never do something like:
val foo = Foo()
foo.x = y.z() // not allowed, because `x` is `val`
^ That is the meaning of val
. You cannot reassign values to it. It just is what it is.
OOP encapsulation states that you shouldnât know why you canât set that property, just that you canât. Thus, as a consumer of that class, there is functionally no difference between x
being a final property which cannot be reassigned, or a getter function that has no field to hold state.
Compare this to the Java equivalents:
// like `val x: String = y.z()`
public class Bar {
private final String x = y.z();
public String getX() {
return x;
}
}
// like `val x: String get() { return y.z() }`
// also `val x: String get() = y.z()` (function `=` syntax)
public class Bar {
public String getX() {
return y.z();
}
}
A user of this Bar
class doesnât know anything about x
. The semantics of whatâs going on underneath these are different, but the classâs public API is the exact same. All a consumer knows is there is a getX()
function, but thereâs a distinct lack of setX(String x)
. A user of that class cannot set a value to x
, but they are not able to know why without looking at the classâs internals. Thatâs all that Kotlin is saying with the val
keyword, and literally what is generated by the compiler. There simply is no setX()
function generated.
Now, about the syntax of val
itself:
When you give an initial value to a property, the Kotlin compiler knows it needs to hold it somewhere, so it creates that backing field so it has somewhere to put it. But a user of the class is not able to know that: again, a user of the class just knows there is getX()
as a method on the class (as seen from Java).
When you do not have an initial value to give to the property, the compiler still needs a way to return a value from that getX()
function itâs trying to generate. Thus, youâll need to manually tell it the logic to stick in that function. But again, from the consumer of the class, there is no difference here, as it still just has that same getX()
function (as seen from Java). So you have to provide a get()
function and implement that logic like any other function, with a return
statement inside a block, or using the get() = y.x()
syntax shortcut. In this case, the =
is on the get()
function, not the property itselfClaudiuB
05/29/2020, 10:35 PMval
to understand it better, I know setters and getters and pondered for some time their need in practice while doing java, I see their point fully, a REAL madman would access directly. I did a few projects sort of assuming the val x = y.z()
is syntactic sugar for the get(){}
implementation, oops đ. Cheers for the detailed writeup.
Although the OOP part about not questioning it, pfft, yeah sure, why not? val
var
and their definition and heuristics give a story about the property that uses it, along with their assignment. It's important to me that a val returns a static value created on init or if it's something that's always compiled, that's exactly what my problem ended up being lol. That's how we get OOP2s and 3s, and how regimes rise or fall, etc.Casey Brooks
05/29/2020, 10:45 PMval
means âread-onlyâ, not âimmutableâ, âstaticâ, âconstantâ or anything like that. âread-onlyâ is more appropriate to how itâs implemented, and is more consistent with the various ways val
is used throughout the language in its various contexts. It also supports the weaker, more-general invariant of it in comparison to âfinalâ or other stronger terms