Reputation: 59
I have this lambda that I would like to return the result of String via CommonIdFacade.commonId
, but what is actually returned is the function. MDC.get
returns a string
typealias CommonIdFactory = () -> String
class CommonIdFacade {
companion object {
var commonId: CommonIdFactory = { MDC.get("someKey") }
internal set
}
}
Upvotes: 1
Views: 432
Reputation: 37710
In your code, the type alias says that CommonIdFactory
is a function that returns a string, not just a string:
typealias CommonIdFactory = () -> String
So if you declare commonId
as a CommonIdFactory
, it will itself be a function that needs to be invoked to get the string.
There are several options depending on how you want to access the variable and set it.
If you want commonId
to be a string when you access it, it shouldn't be of type CommonIdFactory
, but of type String
instead.
class CommonIdFacade {
companion object {
var commonId: String = MDC.get("someKey")
internal set
}
}
// get value directly
val id = CommonIdFacade.commonId
// set a new value
CommonIdFacade.commonId = "some value"
This would initialize commonId
immediately to the value of MDC.get("someKey")
, and it will not change unless you set it to a different value. Setting a value will not affect the underlying MDC
here, because MDC
is only used for the initialization of commonId
, then commonId
has its own independent value that can be changed at will.
If what you want is that each access to commonId
gets a fresh value from MDC
, you should write it in a getter:
class CommonIdFacade {
companion object {
var commonId: String
get() = MDC.get("someKey")
internal set(value) {
MDC.set("someKey", value)
}
}
// get value directly
val id = CommonIdFacade.commonId
// set a new value
CommonIdFacade.commonId = "some value"
In this case you should likely implement the setter in a way that modifies MDC, which may or may not be your intention.
Now, if you do want commonId
to be a function, you can declare it as you did, but then you need to access it as a function:
typealias CommonIdFactory = () -> String
class CommonIdFacade {
companion object {
var commonId: CommonIdFactory = { MDC.get("someKey") }
internal set
}
}
// get value by invoking the function
val id = CommonIdFacade.commonId()
// set a different factory
CommonIdFacade.commonId = { SomewhereElse.getValue() }
Last but not least, maybe you want to set different factory functions but access it as a string property nonetheless:
typealias CommonIdFactory = () -> String
class CommonIdFacade {
companion object {
internal var commonIdFactory: CommonIdFactory = { MDC.get("someKey") }
val commonId: String
get() = commonIdFactory.invoke()
}
}
// get the value directly
val id = CommonIdFacade.commonId
// set a different factory
CommonIdFacade.commonIdFactory = { SomewhereElse.getValue() }
In this case you can set new factory functions via a different property, and access the result of the factory via the commonId
property.
Side note: if there is no instance-level state in CommonIdFacade
, you can declare it as an object
itself instead of class
, so you don't have to shove everything into its companion object
:
object CommonIdFacade {
internal var commonIdFactory: CommonIdFactory = { MDC.get("someKey") }
val commonId: String
get() = commonIdFactory.invoke()
}
Side note 2: mutable globals have a tendency to break things. Do you really need this?
Upvotes: 6