0

Consider an interface:

interface Auth { 
  fun doAuth()
}

this can be implemented for multiple APIs:

class GoogleAuth : Auth {
  override fun doAuth(){
    throw NoGoogleAuthImpl();
  }
}
class TwitterAuth : Auth {
  override fun doAuth(){
    throw NoTwitterAuthImpl();
  }
}

Now, a class might want to use one Auth object, or both of them (or another that would definitely come soon). What is the most simple approach for this?

Trying the Strategy pattern, the class can use only one:

class AuthHost : Auth by GoogleAuth() {
  fun onGoogleClick(){
    //This uses GoogleAuth#doAuth
    doAuth()  ​
  ​}

  fun onTwitterClick(){
    // can not do this right now
  }
}
2

The idea of a class AuthHost implemented in terms of an interface Auth is that the class stays generic, with no compile time knowledge which of the available Auth implementations will be actually used at run time.

But when such a class contains methods like onGoogleClick or onTwitterClick, this contradicts the genericity. So if AuthHost is not supposed to be generic, then one can add simply two member variables of type GoogleAuth and TwitterAuth, initialize and use them accordingly.

However, I guess you want to know how to design AuthHost generic manner. Assumed AuthHost is some user interface class, the UI elements for the different authentification services need to be initialized or generated at run time (for example, a dynamically generated button for each available authentication service, or a dynamically filled list element from which the user has to choose one row. For making this possible, the interface Auth will have to be extended to provide additional meta information.

For example, there should be a function getName() to provide a name string of the Auth service. AuthHost then could contain internally a list (or some other container) of Auth objects, use getName() those to fill the visual list for the UI with the names, let the user pick one of the entries and then call doAuth for the related Auth object. This will lead to a design where there is no onGoogleClick or onTwitterClick method in AuthHost any more, but only something like an onAuthChosenClick method.

0

I am far from an expert in Kotlin, but it seems that your problem is using the by keyword here. AuthHost should hold a member of type Auth, but here you're saying that AuthHost itself implements Auth, and delegates that implementation (that's what the by keyword states) to GoogleAuth, explicitly.

What you need to do is instantiate the Auth class you need, and call the relevant one depending on the method called.

 class AuthHost  { 
    val auth : hashMapOf<string, Auth>

    fun onGoogleClick() {
          auth[google].doAuth() ​
    ​} 
    fun onTwitterClick() {
          auth[twitter].doAuth()
    }
} 
2
  • To Fill val auth a developer needs to initialize all of the implementations in the constructor. and to add them to another class, it is necessary to do all of this again. – mrahimygk Apr 6 at 5:53
  • 3
    @mrahimygk, that is where Dependency Injection comes to the rescue. Have a central place where you create the map of Auth instances and inject that in each class that needs it. That central place could also be a factory class. – Bart van Ingen Schenau Apr 6 at 6:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.