Kotlin属性的泛型

83qze16e  于 2022-11-25  发布在  Kotlin
关注(0)|答案(1)|浏览(110)

我试图找到一个更好的方式来说明类MyList示例的属性list应该是扩展List<MyItem>的任何类,所以从下面开始:

class MyItem {

}
abstract class MyList {
    abstract val list: List<MyItem>
    abstract fun first(): MyItem
}

class MyLinkedList: MyList() {
    override val list: List<MyItem> = LinkedList<MyItem>()
    override fun first(): MyItem {
        return (list as LinkedList<MyItem>).first
    }
}

class MyArrayList: MyList() {
    override val list: List<MyItem> = ArrayList()
    override fun first(): MyItem {
        return list[0]
    }
}

这是可以的,虽然我真的很讨厌(list as LinkedList<MyItem>)转换,因为在我的实际用例中,它会使代码不可读或不可维护(因为它比那个简单的例子复杂得多,现在第二次尝试已经更好了:

class MyItem {

}
abstract class MyList<WrappedList: List<MyItem>> {
    abstract val list: WrappedList
    abstract fun first(): MyItem
}

class MyLinkedList: MyList<LinkedList<MyItem>>() {
    override val list = LinkedList<MyItem>()
    override fun first(): MyItem {
        return list.first
    }
}

class MyArrayList: MyList<ArrayList<MyItem>>() {
    override val list = ArrayList<MyItem>()
    override fun first(): MyItem {
        return list[0]
    }
}

这是非常好的,但是在我的用例中,在这种方法中,我最终会做:

abstract class MyList<
        WrappedList1: List<MyItem1>,
        WrappedList2: List<MyItem2>,
        ...
        WrappedListN: List<MyItemN>
        > {
    abstract val list1: WrappedList1
    abstract val list2: WrappedList2
    ...
    abstract val listn: WrappedListN
    ...
}

虽然它做了我想让它做的事情,但它看起来有点重复和多余,感觉应该有类似于:

abstract class MyList {
    abstract val list1: extends List<MyItem1>
    abstract val list2: extends List<MyItem2>
    ...
    abstract val listn: extends List<MyItemN>
    ...
}

也就是在适当的位置创建匿名的“extends”,而不是命名这么多泛型类型。
有没有办法做到这一点?

piztneat

piztneat1#

我试图找到一种更好的方式来说明类MyList示例的属性列表应该是任何扩展List的类
List<MyItem>类型的属性实际上已经是这个意思了。不需要更多的语法。这就是Liskov的替换原则--你应该能够使用任何符合List<MyItem>契约的示例作为这个属性的值。
这将是好的,虽然我真的很讨厌(名单作为LinkedList)铸造
你不一定要选。答案取决于你想达到的目标。你似乎在问题进行到一半时改变了目标。
如果您“只是”希望能够在类的实现中使用具体的列表类型,则只需使用该具体类型的单独(私有)属性,并使用覆盖的属性将其作为父类型公开:

abstract class MyList {
    abstract val list: List<MyItem>
    abstract fun first(): MyItem
}

class MyLinkedList: MyList() {
    private val _list = LinkedList<MyItem>()
    override val list: List<MyItem> = _list
    
    override fun first(): MyItem {
        return _list.first
    }
}

class MyArrayList: MyList() {
    private val _list = ArrayList<MyItem>()
    override val list: List<MyItem> = _list
    override fun first(): MyItem {
        return list[0]
    }
}

现在,如果您也不介意将新类型公开到类之外,那么就更简单了,您只需将被覆盖的属性声明为父属性类型的子类型:

abstract class MyList {
    abstract val list: List<MyItem>
    abstract fun first(): MyItem
}

class MyLinkedList: MyList() {
    override val list: LinkedList<MyItem> = LinkedList<MyItem>()
    override fun first(): MyItem {
        return list.first
    }
}

class MyArrayList: MyList() {
    override val list: ArrayList<MyItem> = ArrayList()
    override fun first(): MyItem {
        return list[0]
    }
}

相关问题