Интерфейс Kotlin с дженериками и кинжалом - PullRequest
0 голосов
/ 30 мая 2019

У меня определен интерфейс, в котором у меня есть универсальный тип со следующим

interface ActivityService<T> {
  fun getActivities(context: Context, listener: GetActivitiesListener<T>)
  fun addActivity(activity: T, context: Context, listener: AddActivityListener)
}

И реализован с помощью

class AwsActivityService : ActivityService<Activity> {

override fun addActivity(activity: Activity, context: Context, listener: AddActivityListener) {
    AddActivityAsyncTask(activity, context, object : AddActivityAsyncTask.ActivityTaskListener {
        override fun onTaskComplete(result: Boolean) {
            listener.onTaskComplete(result)
        }
    }).execute()
}

override fun getActivities(context: Context, listener: GetActivitiesListener<Activity>) {
    GetActivitiesAsyncTask(context, object : GetActivitiesAsyncTask.ActivityTaskListener {
        override fun onTaskComplete(activityList: List<Activity>) {
            return listener.onTaskComplete(activityList)
        }
    }).execute()
}

}

Как вам тогдаопределить обобщение для модуля в Dagger при создании экземпляра AwsActivityService?

@Module
class ActivitiesModule() {

    @Provides
    @Inject
    @Singleton
    internal fun provideActivitiesModule(): ActivityService {
        return AwsActivityService()
    }
}

1 Ответ

0 голосов
/ 30 мая 2019

Вы можете использовать шаблон фабрики для предоставления нескольких классов на основе типа.

@Module
class ActivitiesModuleFactory() {

    @Provides
    @Inject
    @Singleton
    internal fun provideActivitiesModuleFactory(): ActivityServiceFactory {
        return ActivityServiceFactory()
    }
}

class ActivityServiceFactory {

  inline fun <reified T: Any> getActivities(context: Context, listener: GetActivitiesListener<T>) =
    when(T::class) {
      GoogleActivity::class -> google.getActivities(context, listener as GetActivitiesListener<GoogleActivity>)
      AwsActivity::class -> aws.getActivities(context, listener as GetActivitiesListener<AwsActivity>)
      else -> //throw error or use default listener here
    }

  fun addActivity(activity: any, context: Context, listener: AddActivityListener)=
    when(activity) {
      is GoogleActivity -> google.addActivity(activity, context, listener)
      is AwsActivity -> aws.addActivity(activity, context, listener)
      else -> //throw error or use default listener here
    }

  companion object { 
    val aws = AwsActivityService()
    val google = GoogleActivityService()
  }
}
GoogleActivityService : ActivityService<GoogleActivity> {
    override fun addActivity(activity: GoogleActivity, context: Context, listener: AddActivityListener) {
      AddActivityAsyncTask(activity, context, object : AddActivityAsyncTask.ActivityTaskListener {
        override fun onTaskComplete(result: Boolean) {
          listener.onTaskComplete(result)
        }
    }).execute()
    }

    override fun getActivities(context: Context, listener: GetActivitiesListener<GoogleActivity>) {
      GetActivitiesAsyncTask(context, object : GetActivitiesAsyncTask.ActivityTaskListener {
        override fun onTaskComplete(activityList: List<GoogleActivity>) {
          return listener.onTaskComplete(activityList)
        }
    }).execute()
 }

Основная идея - создать фабрику со спутникомобъект, содержащий экземпляры каждого типа, который вам нужен.Эта фабрика имеет интерфейс, который принимает любой тип, а затем использует оператор when с проверкой типа для вызова правильного сервиса операций.Поскольку сопутствующие объекты связаны с классом, существует только один из каждого ActivityService.

...