Found this in my codebase im working in. Is this i...
# getting-started
c
Found this in my codebase im working in. Is this idiomatic kotlin?
Copy code
class Person(
    val nameFirst: String,
    uniqueId_: String,
) {
  val uniqueId = convertToByteArray(uniqueId_)
questions? 1. this class actually has a bunch more vals in the constructor and it was weird to me seeing uniqueId_ without
val
keyword 2. Seems like uniqueId is still a field right, so is there a way this can somehow just become a property with a getter that'll convert the string into byteArray 3. the name of uniqueId_ is odd, no?
l
I'd imagine the more idiomatic Kotlin approach would be to use a Constructor-like function, and make the Person class a data class (assuming there's not more than what's in the snippet)
m
1. It's not too uncommon to see constructors that have both properties and just arguments. 2. It is a property that happens to be backed by a private field in byte code. You could change it to be a calculated property without breaking clients unless they are using reflection to access it. 3. I standard convention is to use a
_
prefix for backing fields whose name conflicts with the public properties. Common example is a mutable list private and a read only list public property. I've not seen a
_
postfix. It would have been possible to declare the two with the same name. But since the type is different, it is a bit confusing. I would be surprised to call a constructor with a string parameter and then have a byte array property from it, with them both having the same name. So I would probably rename one of them to highlight the difference.
y
Just to correct what everyone else has said,
uniqueId_
is not a field. It won't exist in the bytecode as a private field at all. In fact, it's just a constructor parameter.
nameFirst
is both a constructor parameter, a field, and a getter, while
uniqueId_
is a constructor parameter, and
uniqueId
is a field and a getter. I'd say the idiomatic way to do this would actually be:
Copy code
class Person(
    val nameFirst: String,
    uniqueId: String,
) {
  val uniqueId = convertToByteArray(uniqueId)
because it's perfectly fine to shadow a constructor parameter with a property (arguably, that's what
val nameFirst
does anyways)
e
Copy code
class Person(
    val name: String,
    val uniqueId: ByteArray,
) {
    constructor(
        name: String,
        uniqueId: String, 
    ) : this(
        name = name,
        uniqueId = uniqueId.toByteArray(),
    )
}
👍 2
r
@ephemient Note that that's not the same. The original seems to be intentionally written to NOT accept a byte array as a constructor parameter, whereas yours explicitly allows it. (Also, we don't actually know what
convertToByteArray
is doing, so it's not safe to replace it with
toByteArray
.)
e
it's tweakable to whatever the requirement is.
private constructor
or
convertToByteArray
or whatever, I just didn't want to have to type it out
j
No need for any _. Embrace name shadowing
👍 1
k
I agree that name shadowing is better. Unfortunately, sometimes IntelliJ IDEA issues a warning that a name is shadowed, even when that is deliberate, and I don't want to turn it off in case I miss accidental shadowing, and don't want to suppress it because that brings clutter to the code.
👍 1