我在Kotlin的泛型/接口/实现中苦苦挣扎。
问题是为什么我不能像这样将实现传递给 HabitsRepository :
class HabitsRepository(habitDao: HabitDao, habitConverter: HabitConverter) :
AbstractRepository<AbstractDataSource<AbstractEntity>, AbstractConverter<AbstractModel, AbstractEntity>>(
habitDao,
habitConverter
)
我遇到以下错误
我的设置如下:
习惯存储库
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))
}
答案 0 :(得分:4)
t
不是HabitDao
。它定义为AbstractDataSource<AbstractEntity>
。如果没有将泛型定义为AbstractDataSource<Habit>
或in
,则它是不变,这意味着您必须传递具有确切类型的参数,而不是超类型或子类型。您的out
及其超类的泛型都有类似的问题。
再走一步,您的HabitConverter
是HabitDao
的子类,因此您可以在两个层次上打破不变性。
您的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
都是其通用类型的生产者和使用者,因此它们的类型必须是不变的。