【问题标题】:How do I resolve this diamond problem in Kotlin?如何在 Kotlin 中解决这个钻石问题?
【发布时间】:2019-08-16 03:55:45
【问题描述】:

我有一个接口,用作我的 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(): Int 定义在 GroupHomeDataSource 因为它继承了它的多个接口方法

目前,我通过将两个接口都存储为变量来避免这个问题:

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

或者我是否在确定哪个接口调用它时实现该方法(是否有方法)?

【问题讨论】:

    标签: android kotlin


    【解决方案1】:

    编译器不能自行在多个实现之间进行选择。但是,整个实现看起来有点不堪重负。通常你不应该为每种情况创建扩展的DataSource,而是使用通用接口。如果 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)
    }
    

    【讨论】:

    • 谢谢。在我制作扩展接口的时候,我还没有学习 Kotlin 泛型,所以这会很有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-04
    • 2022-01-07
    • 2019-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多