kotlin - 一个类中的多种类型

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

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

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()
}

我想更改 backPack 类以允许使用不同类型的项目。例如,健康药水和法力药水。我考虑过把这个项目变成一个公开课,然后有这样的东西:

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

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

回答1

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

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

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 怎么办?您可以使用接口来组合您的对象,方法是为其提供多种类型,而不仅仅是父对象:

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。能够将对象视为不同的类型称为多态性。因此,您可以组合不同类型的对象,为其赋予某些属性、某些行为等

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

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

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,并且您可以通过类的函数和属性控制如何访问它们。任何 Item 类型的东西都可以进去!

回答2

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

顺便说一句,类名应该总是以大写字母开头,这样你的代码会更容易阅读。您可以在声明站点初始化属性,而不是使用单独的 init 块。

class Backpack {
    var item: Item? = null

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

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

相似文章

python - 从字符串反向索引

对于输入文本:我想收到以下解决方案:rafal“r”0-5“一”1-4"f"2-3“一”3-2"l"4-1其中第一列是文本中给出的字母,第二列是索引values,第三列是反向索引values。我进行了...