我正在制作一个简单的游戏来学习一些 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 class
或 interface
。一般的 OOP 原则是您应该避免深层类层次结构。如果您的超类不包含必须由所有子类共享的逻辑,则它可能应该是一个接口。