Kotlin static factory method with generics

308 Views Asked by At

Found something similar with what I want to achieve for java - java generics and static methods also implementing factory pattern with generics in java from baeldung.

In my case, I also want to have the factory as a static method, but not sure how to achieve it in Kotlin, or maybe the whole concept is wrong. Shortly, there are certain types of Notifiers, each should handle a certain NotificationInput type. Basically they are also some kind of builders as they build up the Notification object from the input.

Considering the setup below, I get Type mismatch. Required: Notifier<T> Found: DebugNotifier (same for the other Notifier implementations).

interface Notifier<T> {
   fun issue(p: NotificationInput<T>): Notification

   companion object {
      fun <T> getNotifier(p: NotifierParameter): Notifier<T> = when(p.type){
          "0" -> DebugNotifier()
          "1" -> InfoNotifier()
          "2" -> ErrorNotifier()
      }
}

class DebugNotifier: Notifier<Debug>{
   override fun issue(p: NotificationInput<Debug>): Notification{
      return Notification(
         somField = p.someDebugFieldValue
      )
   }
}

data class NotificationInput<T>(
   val data: T
)

This is how I plan to call it: Notifier.getNotifier<Debug>(notifierParameter).issue(notificationInput)

How can this be achieved, or what would be a better configuration?

1

There are 1 best solutions below

2
Joffrey On

As @broot already explained, the caller has control over 2 things here: the type argument T and the NotifierParameter argument, so the API is kinda broken because the caller could do:

Notifier.getNotifier<Debug>(NotifierParameter("2"))

What would you expect to happen here?

There are too many degrees of freedom in the inputs of getNotifier(), so the compiler cannot allow you to return ErrorNotifier() when you receive "2", because someone could pass <Debug> as type argument.

You cannot compare this kind of API with Java, because Java's generics are broken and allow things that don't make sense.