Kotlin类型系统-如何将属性“添加”到两个相关类的子类中

时间:2019-08-10 11:09:45

标签: kotlin

我有两个库类,ItemItemFood : Item(从Item派生),还有一个库函数registerItem(item: Item, name: String)。我无法修改它们。

我有两个自己的类(ItemKey : ItemItemBerry : ItemFood),它们是从库类派生的。

我想要的是将name: String属性存储在我的类ItemKeyItemBerry中,并使其作为“ NamedItem”计数,因此我可以编写一个函数像这样:

fun registerNamedItem(namedItem: NamedItem) {
    registerItem(namedItem, namedItem.name)
}

我不能仅仅像这样创建一个类:class NamedItem(val name: String) : Item并从中派生我的类,因为有时我需要从ItemFood派生我的类,而不是从Item派生我的类。

我不想创建类似class NamedItem(val item: Item, val name: String)的类包装器,因为那样的话,每次我想获取“底层” Item时,我都需要手动获取item属性:registerItem(namedItem.item, namedItem.name),这很丑。

我不能使用interface INamedItem { val name: String }并在ItemKeyItemBerry中实现此接口,因为那样我就需要以这种方式编写函数:

fun registerNamedItem(item: Item, namedItem: INamedItem) {
    registerItem(item, namedItem.name)
}

,这根本没有改善。

是否存在某种先进的技术-使用接口,委托,泛型或其他方式-因此我可以按自己的意愿实现registerNamedItem函数-将{的实例传递给registerItem(item: Item, name: String)将{1}}作为第一个参数并将NamedItem作为第二个参数?

1 个答案:

答案 0 :(得分:0)

实际上,您可以为此使用界面:

fun main() {
    registerNamedItem(ItemKey("item_key"))
    registerNamedItem(ItemBerry("item_berry"))
}

// Cannot change this
open class Item

// Cannot change this
open class ItemFood : Item()

// This is your class
class ItemKey(override val name: String) : NamedItem()

// This is also your class
class ItemBerry(override val name: String) : NamedFoodItem()

// This is the property you would like to enforce
interface INamedItem {
    val name: String
}

// Since Item and ItemFood are concrete classes, you don't have much choice there
abstract class NamedItem : Item(), INamedItem    
abstract class NamedFoodItem : ItemFood(), INamedItem

// Adapter pattern
fun registerNamedItem(namedItem: NamedFoodItem) {
    registerItem(namedItem, namedItem.name)
}

// Adapter pattern
fun registerNamedItem(namedItem: NamedItem) {
    registerItem(namedItem, namedItem.name)
}

fun registerItem(namedItem: Item, name: String) {
    println("Item $namedItem registered with $name")
}

在您的情况下,委托不起作用,因为从您的示例中来看,Item是一个类,并且您只能委托给接口。