Kotlin ENUM classes with common interface implemented by delegates
Asked Answered
A

1

10

This is a slightly abstract question about finding a pretty design approach with minimal boilerplate.

Prerequisites:

  • I have an ENUM class for enumerating various providers i.e.: enum class Provider { Google, Microsoft }
  • Let’s say there is a service interface interface Foo { fun getMail(): Mail } that will be implemented for each specific provider.

I was curious if there is a way to define ENUM class Provider in such way that it’s implementing interface Foo and I can later specify by which objects each concrete provider will be implemented?

I wonder if there can be a boilerplate-less way to define enum class of concrete interface while I can later define by which objects concrete provider will be implemented.

Prerequisites aren’t solid so if a better design requires changes then I’m eager for a better suggestion.

Afterheat answered 20/3, 2018 at 20:13 Comment(2)
How much later do you want to specify which implementation to delegate to? Do you want these implementation classes not to be hardcoded into the enum? What if you just had a factory class that gives you the appropriate Foo implementation based on the enum key you provide to it?Praline
The idea is to have enumerated entries Google and Microsoft being also aliases to some specific instances of corresponding services or simply delegate whole interface implementation to other objects (that more likely to be initialized later.)Afterheat
B
20

Yep

You can make the enum implements the interface.

enum class Provider(val mail: Mail) : Foo {
    Google(googleMail),
    Microsoft(microsoftMail);

    override fun getMail(): Mail = mail // Or this.mail
}

interface Foo { fun getMail(): Mail }

Then you access

Provider.Google.getMail()

Other way is using val members

interface Foo { val mail: Mail }

enum class Provider(override val mail: Mail) : Foo {
    Google(googleMail),
    Microsoft(microsoftMail)
}

And access

Provider.Google.mail
Butyraceous answered 21/3, 2018 at 0:27 Comment(5)
So googleMail and microsoftMail are service instances that are the values of the enumerated entries? Also if I have to override each method of the interface then it seems like enum itself can be an interface.Afterheat
Yep. But enum cannot extends other classes neither other enum, only interfacesButyraceous
I noticed it is possible to use by keyword to delegate interface implementation of the enum class. I wanted to find a solution where I can change delegate during runtime.Afterheat
If I'm not wrong, delegates cannot be changed, when you set the variable, is called a setter method of your delegate object. If you just want to change the variable mail value, change val for varButyraceous
I’m sorry, I think my example was a little bit misleading, as getMail is not a getter but an interface method to be implemented by the service while each enumeration should correspond to the different implementation of that interface.Afterheat

© 2022 - 2024 — McMap. All rights reserved.