Kotlin中的泛型。如何通过泛型传递Abstract类的实现

时间:2020-05-18 22:13:30

标签: generics kotlin syntax architecture

我在Kotlin的泛型/接口/实现中苦苦挣扎。

问题是为什么我不能像这样将实现传递给 HabitsRepository

class HabitsRepository(habitDao: HabitDao, habitConverter: HabitConverter) :
    AbstractRepository<AbstractDataSource<AbstractEntity>, AbstractConverter<AbstractModel, AbstractEntity>>(
        habitDao,
        habitConverter
    )

我遇到以下错误

enter image description here

我的设置如下:

习惯存储库

 class HabitsRepository(habitDao: HabitDao, habitConverter: HabitConverter) :
    AbstractRepository<AbstractDataSource<AbstractEntity>, AbstractConverter<AbstractModel, AbstractEntity>>(
        habitDao as AbstractDataSource<AbstractEntity>,
        habitConverter as AbstractConverter<AbstractModel, AbstractEntity>
    )

习惯岛

@Dao
interface HabitDao : AbstractDataSource<Habit>{

    @Query("SELECT * FROM habit WHERE id=:id ")
    override fun getById(id: String): Single<Habit>

    @Query("SELECT * FROM habit")
    override fun getAll(): Single<List<Habit>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    override fun insert(entity: AbstractEntity): Completable

    @Delete
    override fun delete(habit: AbstractEntity) : Completable

    @Update
    override fun update(habit: AbstractEntity): Completable
}

HabitConverter

class HabitConverter : AbstractConverter<HabitModel, Habit> {
    override fun toModel(entity: Habit): HabitModel {
        return HabitModel()
    }

    override fun toEntity(model: HabitModel): Habit {
        return Habit()
    }
}

HabitDatabaseSource

class HabitDatabaseSource @VisibleForTesting constructor(private val habitDao: HabitDao) : HabitDao {

    override fun getById(id: String): Single<Habit> = habitDao.getById(id)

    override fun getAll(): Single<List<Habit>> = habitDao.getAll()

    override fun insert(entity: AbstractEntity): Completable = habitDao.insert(entity)

    override fun delete(habit: AbstractEntity): Completable = habitDao.delete(habit)

    override fun update(habit: AbstractEntity): Completable = habitDao.update(habit)
}

AbstractDataSource

interface AbstractDataSource<T : AbstractEntity> {
    fun getById(id: String): Single<T>
    fun getAll(): Single<List<T>>
    fun insert(entity: AbstractEntity): Completable
    fun delete(entity: AbstractEntity): Completable
    fun update(entity: AbstractEntity): Completable
}

AbstractEntity / AbstractModel

abstract class AbstractEntity
abstract class AbstractModel

AbstractConverter

interface AbstractConverter<AM: AbstractModel, AE: AbstractEntity>{
    fun toModel(entity: AE) : AM
    fun toEntity(model: AM): AE
}

AbstractRepository

abstract class AbstractRepository<ADS: AbstractDataSource<AbstractEntity>, AC: AbstractConverter<AbstractModel, AbstractEntity>>(
    private val abstractDataSource: ADS,
    private val abstractConverter: AC
){
    fun getById(id: String): Single<AbstractModel> {
        return abstractDataSource.getById(id).map { abstractConverter.toModel(it) }
    }

    fun getAll(): Single<MutableList<AbstractModel>> =
        abstractDataSource.getAll().flattenAsObservable {it}.map { abstractConverter.toModel(it) }.toList()

    fun insert(model: AbstractModel): Completable = abstractDataSource.insert(abstractConverter.toEntity(model))

    fun delete(model: AbstractModel): Completable = abstractDataSource.delete(abstractConverter.toEntity(model))

    fun update(model: AbstractModel): Completable = abstractDataSource.update(abstractConverter.toEntity(model))
}

1 个答案:

答案 0 :(得分:4)

t不是HabitDao。它定义为AbstractDataSource<AbstractEntity>。如果没有将泛型定义为AbstractDataSource<Habit>in,则它是不变,这意味着您必须传递具有确切类型的参数,而不是超类型或子类型。您的out及其超类的泛型都有类似的问题。

再走一步,您的HabitConverterHabitDao的子类,因此您可以在两个层次上打破不变性。

您的AbstractDataSource必须声明所使用的Habit类的确切类型:

HabitRepository

至少对于您的class HabitsRepository(habitDao: HabitDao, habitConverter: HabitConverter) : AbstractRepository<HabitDao, HabitConverter>( habitDao, habitConverter ) ,泛型类型仅出现在生产位置,因此您可以将其类型声明为AbstractRepository,而不会失去任何功能:

out

然后您对abstract class AbstractRepository<out ADS: AbstractDataSource<AbstractEntity>, out AC: AbstractConverter<AbstractModel, AbstractEntity>> ( //... 的定义可能会放松一些:

HabitsRepository

但是class HabitsRepository(habitDao: HabitDao, habitConverter: HabitConverter) : AbstractRepository<AbstractDataSource<Habit>, AbstractConverter<HabitModel, Habit>>( habitDao, habitConverter ) AbstractDataSource都是其通用类型的生产者和使用者,因此它们的类型必须是不变的。