Initializing interface instance variables - interface

I would like to inject (enrich) behavior and state in a Kotlin class by using an interface. Like class Impl : Observable, where Observable contains state.
In Scala using Traits (does work), looking for a Kotlin solution for this one:
object Test extends App {
val impl = new Impl()
val observer = new Observer()
impl.register(observer)
}
trait Observable {
// How to do this in Kotlin?
val observers = List()
def register(observer: Observer) {
observers.add(observer)
}
}
class Observer
class Parent
class Impl extends Parent with Observable
Attempt in Kotlin (not working):
fun main(args: Array<String>) {
val impl = Impl()
val observer = Observer()
impl.register(observer)
}
interface Observable {
// Error: Kotlin: Property initializers are not allowed in interfaces
val observers = mutableListOf<Observer>()
fun register(observer: Observer) {
observers.add(observer)
}
}
class Observer
open class Parent
class Impl : Parent(), Observable
It results in this error at the interface instance variable line: Kotlin: Property initializers are not allowed in interfaces.
How can I initialize instance variables in Kotlin interfaces?
(Note that in this design, parent classes shouldn't be altered/updated.)
UPDATE: I had an example solution in Java, but that wasn't behaving correctly. "Instance variables" in Java interfaces are automatically static. So I have removed that example.

You can have a placeholder for state in Kotlin interfaces, and let the implementing class provide that state. So the interface can provide the functionality that works against the expected-to-exist state. Such as:
class Observer
interface Observable {
val observers: MutableList<Observer> // not present, but expected
fun register(observer: Observer) {
observers.add(observer)
}
}
open class Parent
class Impl : Parent(), Observable {
override val observers = mutableListOf<Observer>() // used by the interface
}
This is for good reason, there are delicate issues having state coming from more than one item in the class hierarchy and Kotlin is preventing the problems that can arise from such models.

In Java you actually have a static field, not an instance field (unlike Scala code, which does work as you expect):
Every field declaration in the body of an interface is implicitly public, static, and final.
You can achieve the same behavior in Kotlin by putting the field into a companion object.
But what you should actually do is use an abstract class instead of an interface.
Or delegation:
interface Observable {
fun register(observer: Observer)
}
class ObserverList : Observable {
val observers = mutableListOf<Observer>()
override fun register(observer: Observer) {
observers.add(observer)
}
}
class Impl : Parent(), Observable by ObserverList()

Related

Override trait function in the intersection of two mixins

The thing is, is there any way (That does not involve reflective black magic), to implicitly override a method, when two known traits are implemented?
Think that we have a class SysImpl that implements two mixins: System and Container:
// Where system acts as the interface for another consumer
trait System {
def isEmpty = false
}
trait Container[A] {
val elements = mutable.Set[A]()
}
// Then, we typically implement:
class SysImpl extends System with Container[Int] {
// We override the default system implementation here
override def isEmpty = elements.isEmpty
}
Just as an example.
Is there any way of implementing either a third trait, or making something to the original, that makes the implementation implicitly override the isEmpty method, in case that System & Container[A] are present?
The first thing that comes to my mind is creating an extension method, but that would be shadowing at its best (Wouldn't it?). I need the method to be overridden properly, as the call is dispatched by a consumer who only sees Systems.
(Example, omitting details)
class AImpl extends System with Container[A]
object Consumer {
def consume(sys: System) = if (sys.isEmpty) { /* Do things */ }
}
// Somewhere...
object Main {
def main() = {
Consumer.consume(new AImpl)
}
}
Just
trait Mix[A] extends Container[A] with System {
override def isEmpty = elements.isEmpty
}

Dependency Injection on Class Instantiated Elsewhere

I am trying to inject ehcache via the Play Framework. I am injecting it into a companion class, but that class is being instantiated in an abstract class elsewhere as well as the companion object. I do not want to inject anything into the abstract class because it is being used elsewhere.
For example, this is basically how the companion class and object are set up (removed some logic and extensions for better readability):
class Setting #Inject()(cached: DefaultSyncCacheApi) {
def isCached(id:String): Boolean = {
val cachedItem = cached.get(id)
cachedItem.isDefined
}
}
object Setting {
def getId(id:String): Setting = {
val setting = new Setting //I know this doesn't work
if (setting.isCached(id)) {
//retrieval logic
}
setting
}
}
This is the abstract class where it is being instantiated:
abstract class UsingSettingAbstract {
def methodUsingSetting(): String = {
val setting = new Setting
val str = new String
//logic in here
str
}
}
I have tried to create an empty constructor in the Setting class with def this() { }, and creating a chain of constructors, but have so far been unsuccessful in getting the cache to be successfully injected.
I did different versions of below, initializing the cache variable with cached or trying to pass through cached:
class Setting #Inject()(cached: DefaultSyncCacheApi) {
val cache:DefaultSyncCacheApi
def this() {
this(cache)
}
}
Is there a way to get DI to work with this setup, or would something like a factory pattern work better?
With guice you can pass any created instance to the injectors "requestInjection()" method. This will trigger method and field injection on that instance.
So as long as you have access to the injector, you can get injections done.

Generic getter for multiple Collection in Mongo with Kotlin

I use Kotlin and Mongo (with KMongo) and I have multiple models as UserEntity, MovieEntity and so on. Each of them use a specific Dao class to do (actually) the same methods. Therefore, I'm trying to avoid any duplication by using a BaseDao which should have these methods instead.
So I pass the specific entity in the generic base as:
class UserDao : BaseDao<UserEntity>() { ... }
This base class implements the generic methods as follows:
open class BaseDao<T: Any>() {
fun get(id: String): T? {
return getCollection().findOneById(id)
}
fun save(entity: T): T {
return getCollection().save(entity)
}
fun delete(id: String) {
getCollection().deleteOneById(id)
}
...
}
However, a problem occurs on getCollection() method:
private inline fun <reified T: Any> getCollection(): MongoCollection<T> {
return MongoDb.getDatabase().getCollection<T>()
}
This gets a compilation error each time I call it:
Type inference failed: Not enough information to infer parameter T in
inline fun <reified T : Any> getCollection(): MongoCollection<T#1 (type parameter of app.api.db.dao.BaseDao.getCollection)>
Please specify it explicitly.
I can't find the right way to do this. I already checked these threads but I didn't make it work: Generic class type usage in Kotlin & Kotlin abstract class with generic param and methods which use type param.
Question:
How can I achieve this generic BaseDao which should get any collection of each child Dao?
the JVM forgets the type of the generic T in BaseDao<T: Any>() at runtime, which is why type inference fails. A solution to this could be to pass the KClass of T in the constructor of BaseDao:
open class BaseDao<T: Any>(val kClass: KClass<T>) {
...
}
After this, give your reified function an argument that accepts a `KClass:
private inline fun <reified T: Any> getCollection(val kClass: KClass<T>): MongoCollection<T> {
return MongoDb.getDatabase().getCollection<T>()
}
I'm unaware of a method to do this without passing the KClass as a argument to the function, but this should work, as the generic T can be derived from the provided kClass.
`
Another way would be to make all methods in BaseDao inline function with reified generics and dropping the generic on the class.
open class BaseDao() {
inline fun <reified T: Any> get(id: String): T? {
return getCollection().findOneById(id)
}
inline fun <reified T: Any> save (entity: T): T {
return getCollection().save(entity)
}
inline fun <reified T: Any> delete(id: String) {
getCollection().deleteOneById(id)
}
...
}
This way the generic T can be derived since the method calling getCollection is also reified.
(For KMongo 4.0.+) no need to use reified generics for the each method, instead this base class can be used as as a starting point:
open class BaseDao<T: Any>(
protected val collection: CoroutineCollection<T>
) {
suspend fun get(id: Id<T>): T? {
return collection.findOneById(id)
}
suspend fun save(entity: T): UpdateResult? {
return collection.save(entity)
}
suspend fun delete(id: Id<T>) {
collection.deleteOneById(id)
}
}
And implemented in the particular DAO, say SessionDao:
class SessionDao(collection: CoroutineCollection<DbSession>)
: BaseDao<DbSession>(collection)
(note: inheritance can be replaced with delegation by using by keyword if one feel better this way
This and other dao can be created via DI or some sort of dao factory:
class DbInstance(mongodbConnectionString: String = "mongodb://localhost:27017/myproject") {
private val connectionInfo = ConnectionString(mongodbConnectionString)
val client = KMongo.createClient().coroutine
val db = client.getDatabase(
connectionInfo.database ?: throw IllegalArgumentException("mongodb connection string must include db name")
)
val sessions = SessionDao(db.getCollection())
}
Notes:
This example is for the coroutine based kmongo, it can be easly converted to blocking kmongo by replacing CoroutineCollection to MongoCollection
I assume documents id's are annotated via Id container which helps to mitigate errors, so documents should be created in this fashion:
data class DbSession(
#BsonId
val id: Id<DbSession>,
val name: String,
)
The solution is to use reflection as Zigzago mentioned by using KMongoUtil:
protected fun getCollection(): MongoCollection<T> =
getDaoEntityClass().let { k ->
MongoDb.getDatabase().getCollection(
KMongoUtil.defaultCollectionName(k), k.java)
}
#Suppress("UNCHECKED_CAST")
private fun getDaoEntityClass(): KClass<T>
= ((this::class.java.genericSuperclass
as ParameterizedType).actualTypeArguments[0] as Class<T>).kotlin

Is it possible to specify a static function in a Kotlin interface?

I want to do something like this:
interface Serializable<FromType, ToType> {
fun serialize(): ToType
companion object {
abstract fun deserialize(serialized: ToType): FromType
}
}
or even this would work for me:
interface Serializable<ToType> {
fun serialize(): ToType
constructor(serialized: ToType)
}
but neither compiles. Is there a syntax for this, or will I be forced to use make this an interface for a factory? Or is there another answer? 😮 That'd be neat!
Basically, nothing in a companion object can be abstract or open (and thus be overridden), and there's no way to require the implementations' companion objects to have a method or to define/require a constructor in an interface.
A possible solution for you is to separate these two functions into two interfaces:
interface Serializable<ToType> {
fun serialize(): ToType
}
interface Deserializer<FromType, ToType> {
fun deserialize(serialized: ToType): FromType
}
This way, you will be able to implement the first interface in a class and make its companion object implement the other one:
class C: Serializable<String> {
override fun serialize(): String = "..."
companion object : Deserializer<C, String> {
override fun deserialize(serialized: String): C = C()
}
}
Also, there's a severe limitation that only a single generic specialization of a type can be used as a supertype, so this model of serializing through the interface implementation may turn out not scalable enough, not allowing multiple implementations with different ToTypes.
For future uses, it's also possible to give the child class to a function as a receiver parameter:
val encodableClass = EncodableClass("Some Value")
//The encode function is accessed like a member function on an instance
val stringRepresentation = encodableClass.encode()
//The decode function is accessed statically
val decodedClass = EncodableClass.decode(stringRepresentation)
interface Encodable<T> {
fun T.encode(): String
fun decode(stringRepresentation: String): T
}
class EncodableClass(private val someValue: String) {
// This is the remaining awkwardness,
// you have to give the containing class as a Type Parameter
// to its own Companion Object
companion object : Encodable<EncodableClass> {
override fun EncodableClass.encode(): String {
//You can access (private) fields here
return "This is a string representation of the class with value: $someValue"
}
override fun decode(stringRepresentation: String): EncodableClass {
return EncodableClass(stringRepresentation)
}
}
}
//You also have to import the encode function separately:
// import codingProtocol.EncodableClass.Companion.encode
This is the more optimal use case for me. Instead of one function in the instanced object and the other in the companion object like your example, we move both functions to the companion object and extend the instance.

Delaying trait initialization

I need a smart mechanism for component composition which allows mixed in traits to initialize after the composed component. The following throws a NullPointerException:
class Component {
def addListener(pf: PartialFunction[Any, Unit]) {}
}
trait DynamicComponent {
protected def component: Component
component.addListener {
case x =>
}
}
class Foo extends DynamicComponent {
protected val component = new Component
}
new Foo // -> NullPointerException
The following things are not options for me:
Using protected lazy val component; that would produce an avalange of dozens of vals needing to become lazy, something I do not want.
Putting addListener in a method, e.g. initDynamic(); because I will be mixing in many traits, and I don't want to remember to call half a dozen initFoo() methods.
Using DelayedInit. This doesn't work with traits, at least according to the scaladocs.
I could live with a single init() call, but only under the following conditions:
all mixed in traits can easily declare to be invoked in this one single call
it is a compile error to forget the init() statement.
You can delay the initialization of a trait by by using early definitions. (See section 5.1.6 of the scala language specification)
class Foo extends {
protected val component = new Component
} with DynamicComponent
It's even clunkier than your solution, but you can always require the creation of a val that must be set with the init() method. You could choose to not do it last and get an error at runtime, but at least you won't forget it entirely:
class Component {
def addListener(pf: PartialFunction[Any, Unit]) {
println("Added")
}
}
trait Dyn {
protected def component: Component
protected val initialized: Init
class Init private () {}
private object Init { def apply() = new Init() }
def init() = { component.addListener{ case x => }; Init() }
}
class Foo extends Dyn {
protected val component = new Component
protected val initialized = init()
}
No cheating!:
> class Bar extends Dyn { protected val component = new Component }
<console>:12: error: class Bar needs to be abstract, since value
initialized in trait Dyn of type Bar.this.Init is not defined
class Bar extends Dyn { protected val component = new Component }
The advantage this has is if you need multiple things to be in place before you initialize all of them cooperatively, or if your Component class is final so you can't mix in anything else.
AN idea could be to use the trick described here:
Cake pattern: how to get all objects of type UserService provided by components
All your components that should be initialized could be registered in some Seq[InitializableComponent]. And then you could initialize all registered components with a foreach.
No component will be forgotten in that Seq because they are registered automatically, but you can still forget to call the foreach anyway...
Here is one idea (I am happy to read about other suggestions):
class Component {
def addListener(pf: PartialFunction[Any, Unit]) {
println("Added")
}
}
trait DynamicComponentHost {
protected def component: Component with DynamicPeer
protected trait DynamicPeer {
_: Component =>
addListener {
case x =>
}
}
}
class Foo extends DynamicComponentHost {
protected val component = new Component with DynamicPeer
}
new Foo
So basically I am forcing the component to mix in a type that can only be provided by the mixed in trait. Reasonable? Looks a bit too complicated in my eyes.