如何解决科特林的钻石问题?

时间:2019-08-16 03:55:45

标签: android kotlin

我有一个接口,它用作RecyclerView适配器的通用数据源,如下所示:

interface GenericRVAdapterDataSource {
    fun getCellCount() : Int
    fun getViewModelForCell(position : Int) : CellViewModel
}

现在,我还有另外两个接口可以扩展这个接口:

interface GroupHomeDataSource : GenericRVAdapterDataSource {
    fun getJoinedGroupsCount() : Int
    fun getJoinedGroupViewModel(forIndex : Int) : GroupHomeCellViewModel

    override fun getCellCount(): Int = getJoinedGroupsCount()
    override fun getViewModelForCell(position: Int): CellViewModel = getJoinedGroupViewModel(position)
}

和:

interface GroupSuggestedDataSource : GenericRVAdapterDataSource {
    fun getSuggestedGroupsCellCount() : Int
    fun getSuggestedGroupViewModelForCell(atIndex : Int) : GroupHomeCellViewModel

    override fun getCellCount(): Int = getSuggestedGroupsCellCount()
    override fun getViewModelForCell(position: Int): CellViewModel = getSuggestedGroupViewModelForCell(position)
}

但是,当我将两个接口都实现到类中时:

class GroupHomeViewModel(app : Application) : AndroidViewModel(app), GroupHomeDataSource, GroupSuggestedDataSource, GroupsHomeInteractionLogic {...}

我得到了错误:

  

'GroupHomeViewModel'类必须重写public open fun getCellCount():GroupHomeDataSource中定义的Int,因为它继承了它的多个接口方法

现在,我仅通过将两个接口都存储为变量来避免了这个问题:

val joinedGroupsDataSource = object: GroupHomeDataSource {
    override fun getJoinedGroupsCount(): Int = joinedGroupsList.size
    override fun getJoinedGroupViewModel(forIndex: Int): GroupHomeCellViewModel = joinedGroupsList[forIndex]
}

val suggestedGroupsDataSource = object: GroupSuggestedDataSource {
    override fun getSuggestedGroupsCellCount(): Int = suggestedGroupsList.size
    override fun getSuggestedGroupViewModelForCell(atIndex: Int): GroupHomeCellViewModel = suggestedGroupsList[atIndex]
}

但是,我不确定这是否是解决钻石问题的最有效方法-如果我什至可以这样称呼。

我是否只执行编译器告诉我的操作并实现getCellCount(),然后使用以下命令将其重定向到接口的实现之一:

//MARK:- super interface implementation

override fun getCellCount(): Int {
    return super<GroupHomeDataSource>.getCellCount()
    //Or: return super<GroupSuggestedDataSource>.getCellCount()
}

override fun getViewModelForCell(position: Int): CellViewModel {
    return super<GroupHomeDataSource>.getViewModelForCell(position)
    //Or: return super<GroupSuggestedDataSource>.getViewModelForCell(position)
}

//ENDMARK

还是在确定哪个接口需要它的同时实现该方法(是否有此方法)?

1 个答案:

答案 0 :(得分:1)

编译器无法自行选择多个实现。但是,整个实现看起来有些不知所措。通常,您不应该为每种情况创建扩展的DataSource,而应使用Generic接口。如果GroupHomeViewModel提供了多个数据源,则只需像创建操作一样创建不同的属性即可。

interface CellViewModel
interface GroupHomeCellViewModel : CellViewModel

interface RVAdapterDataSource<T : CellViewModel> {
    fun getCellCount() : Int
    fun getViewModelForCell(position : Int) : T
}

class ListAdapterDataSource<T : CellViewModel>(
  private val list: List<T>
) : RVAdapterDataSource<T> {
    override fun getCellCount() = list.size
    override fun getViewModelForCell(forIndex: Int) = list[forIndex]
}

class GroupHomeViewModel(
    joinedGroupList: List<GroupHomeCellViewModel>,
    suggestedGroupList: List<GroupHomeCellViewModel>
) {
  val joinedGroupsDataSource = ListAdapterDataSource(joinedGroupList)
  val suggestedGroupsDataSource = ListAdapterDataSource(suggestedGroupList)
}