class 中的多种类型的 class

Multiple types of a class within a class

我正在制作一个简单的游戏来学习一些 kotlin,但我对使用 OOP 改变这种情况的最佳方法有点困惑。

我有一个 class 用于背包设置,所以它有另一个 class 称为项目,将是不同类型的项目。下面我重新创建了一个简单的版本。

class backPack {
      private val item: Item

init { item = Item() }

     fun display() {
     item.display()
     }
}

class Item {
      fun display() { println("Your item!") }
}

fun main() {
 val examplePack = backPack()
 examplePack.display()
}

我想更改背包 class 以允许不同类型的物品。例如,健康药水和法力药水。我考虑过将项目设为开放 class,然后是这样的:

class healthPotion : Item() {
    override fun display() {
        println("health potion!")
    }
}
class manaPotion : Item() {
    override fun display() {
        println("mana potion!")
    }
}

这似乎是正确的,但我对如何重构背包 class 以允许不同类型的物品有点困惑,我想确保这似乎是一种正确的方法。非常感谢任何帮助,谢谢!

基本上就是这个主意!如果您的 BackPack class(按照惯例它应该以大写字母开头)处理 Item,那么任何具有该类型的 class 都可以工作。您有两个选择 - 继承和组合。

继承是构建 class 层次结构的地方,例如:

open class Item {
    val weight: Int
    fun Describe()
}

open class Potion : Item() {
    fun drink() {}
}

// this is a Potion, and a Potion is an Item, meaning this is an Item
class ManaPotion : Potion() {
    override fun drink() {
       println("whoa!")
    }
}

// etc

问题是您被严格的等级制度所束缚 - 如果您有 StaleBread 那是 Food,但您还希望它是 Weapon 怎么办?您可以使用 interfaces 通过给它多种类型来组合您的对象,而不仅仅是一个父类:

open class Item

interface Food {
    fun eat() {
        println("yum")
    }
}

interface Weapon {
    fun attack() {
        println("RARGH")
    }
}

class StaleBread : Item(), Food, Weapon

因为StaleBread有所有这些类型,你可以把它当作任何,因为它所有他们中的。因为它是一个Weapon,所以它保证有一个attack()方法,等等。你可以将它添加到一个List<Food>,因为它is一个Food。能够将对象视为不同的 类型 称为 多态性 。因此,您可以组合 不同类型的对象,赋予它某些属性、某些行为等


您的示例应该有效 as-is 因为您在背包中处理 Item,并且您的两个药水 class 都是 Item(的后代class,具体来说,因为您继承自 Item class)。有很多方法来组织它——如果你学习了一些关于继承、组合和多态性的教程(这只是一个简单的概述,跳过了一堆东西)你会开始对如何前进有一些想法


哦,是的,对于实际的背包,您可能想要这样的东西:

class BackPack {
    private val items = mutableListOf<Item>()

    fun addItem(item: Item) {
        // here you could do things like check it doesn't exceed the allowed weight
        // or capacity of the backpack
        items.add(item)
    }
}

这样,您的背包可以包含多个 Item,并且您可以通过 class 的函数和属性来控制如何访问它们。任何 Item 类型的东西都可以放在那里!

如果您希望能够更改包中的物品,属性 应该是 var。如果您希望袋子能够为空,那么它应该是可以为空的 属性(在类型后用 ? 声明,以便它可以容纳 null)。

顺便说一句,class 名称应始终以大写字母开头,以便您的代码更易于阅读。您可以在声明站点初始化属性,而不是使用单独的 init 块。

class Backpack {
    var item: Item? = null

    fun display() {
        item?.display()
    }
}

您的通用 Item() 似乎在实践中没有用处。因此,Item 应该是 abstract classinterface。一般的 OOP 原则是您应该避免深度 class 层次结构。如果您的 superclass 不包含必须由其所有子级共享的逻辑,它可能应该是一个接口。