Are there a set of rules people follow about where...
# getting-started
t
Are there a set of rules people follow about where to declare instance variables in Kotlin? Ideally, I just want them in a single terse vertical list, so every time I look at a class declaration I see something like:
TheNewClass:TheParentClass {
var a:Foo
var b:Bar
var c:Baz
}
But primary constructors make it more interesting. Now I can declare them right in one line, which I don't mind when it's just that guy, something like:
data class Point<T>(val x:T, val y:T) { }
Now I've got to decode two types of object declarations when looking at them. But then I can mix and mash them:
Copy code
class BLEConduit(val peripheral:BLEPeripheral):ConnectionConduit {
   var sendBuffer = ubyteArrayOf() 
   var receiveBuffer:UByteArray? = null
So now I'm having to parse (and rationalize) two lists, to get at what the "guts" of an object is. And if I mix parameters without val/var in the primary constructor, any conciseness really breaks down. Are there a set of rules/guidelines others follow on when to put what where? To me, Kotlin's properties/init/constructors feels very evolutionary, like they started in one place, and then evolved things, but left backwards compatibility in place, and now there's less of a clear/idiomatic way to declare what an object is and how it gets initialized.
đź‘Ť 1
n
it depends on where the data is coming from -- do you need to pass it in or not. if yes, constructor. whatever gets you closer to read-only/immutable types.
t
Fair enough, so replace any var's there with val's. Now they're all read only immutable types. The question still stands
n
I dunno man, properties and constructor arguments feel completely different to me, so it's hard to explain without commenting on a specific class
t
so do you never use var/val inline in your constructors?
n
we use a lot of Guice, and all the injected bindings come in through the constructor
c
I always use a syntax like the following:
Copy code
class BLEConduit(
    val peripheral:BLEPeripheral
): ConnectionConduit {

   var sendBuffer = ubyteArrayOf()
   var receiveBuffer:UByteArray? = null

}
Even if there’s only 1 constructor parameter, it goes on the next line, and the superclass also goes on the next line after parameters. So the superclass or opening class bracket gives me that nice, clear separation between properties that are passed in vs the ones that are in the class body. In addition to using
val
whenever possible, I also usually put those “class body” properties as extensions to the class, rather than within the class itself. If everything is immutable, then there’s really nothing to hide, so those properties don’t need to be directly inside the class. For the most part, the only “class body” variables I use regularly are some kind of property delegate, or
lateinit var
and injected
o
TBH the biggest readability issue in your example are the missing spaces before types. Kotlin style guide prescribes them.
BLEConduit(val peripheral:BLEPeripheral):ConnectionConduit
really is difficult to decode.