我什么时候应该创建子类而不是类的实例?

Jak*_*fan 5 python oop

我如何知道何时将某些东西设为类而不是类的实例?例如:

如果我正在创建一个太空游戏(我不是),并且我希望环境是宇宙,我会写:

class Universe:
    def __init__(self):
        pass
Run Code Online (Sandbox Code Playgroud)

现在假设我想用星系填充我的宇宙,所以我将创建一个 Galaxy 子类,并带有大小和名称参数:

class Galaxy(Universe):
    def __init__(self, size, name):
        super().__init__(self):
    self.size = size
    self.name = name
        pass
Run Code Online (Sandbox Code Playgroud)

接下来,我想制作行星。如果是这样的话,我应该创建 Galaxy 子类的子类,对吧?

class Planet(Galaxy):
    def __init__(self, type, climate):
        super().__init__(self, size, name):
    self.type = type
    self.climate = climate
        pass
Run Code Online (Sandbox Code Playgroud)

从这里我想创建行星类型,或“家族”。解决这个问题的最佳方法是什么?子类的另一个子类?每个行星都将包含该行星家族独有的资源。我应该这样做吗:

class PlanetType(Planet):
    resources = []
    def __init__(self, resources):
        super().__init__(self, type, climate) 
    self.resources = resources
        pass
Run Code Online (Sandbox Code Playgroud)

Chr*_*lou 6

所以这并不是Python特有的,它更多的是OOP(面向对象编程)的核心思想

我如何知道何时将某些东西设为类而不是类的实例?

答案:在你的例子中,宇宙是超类,你想创建行星的概念。如果 Planet 继承(子类)自 Universe,则意味着它们具有“是”关系。我将在这里举另一个流行的例子来说明我的观点。

假设您有一辆轿车。玛莎拉蒂将是这个超类的子类(将继承),因为玛莎拉蒂是一辆汽车。如果您想将 Wheels 表示为一个类,那么说 Wheels IS a Car 就没有意义。汽车有轮子。所以Wheels Class应该是Car中的一个实例变量。回到你的例子。宇宙有星系,星系有行星。但行星不是星系,星系也不是宇宙。

  • 非常小的编辑建议:说“玛莎拉蒂”,而不是“玛莎拉蒂”;“玛莎拉蒂”将是玛莎拉蒂类别的一个实例,但“玛莎拉蒂”的概念/蓝图将是该类别本身。 (4认同)

Sha*_*ger 2

因此,您的第一个问题是尝试创建一个根本不适合它的类层次结构。当您从另一个类继承时,问问自己“子类是类的类型?”。就你而言,“星系是宇宙的一种吗?” 和“行星是星系的一种吗?” 两者显然都是错误的。

在您遇到的情况下,所有类都应包含较低级别的类型;aUniverse可能包含slistGalaxya,而 s 又包含slistPlaneta。我不知道你在PlanetType这里所说的 a 到底是什么意思( a 似乎完全有可能Planet有一个属性,可能是 an enum.Enum,描述资源的类型和 a list),所以我怀疑这是子类的情况,但如果它真的是这样的话很有用(例如,您需要出现在所有Planets 上但行为因类型而异的方法),声明以下内容可能是合理的:

class GasGiant(Planet):
    ...
class RockyPlanet(Planet):
    ...
Run Code Online (Sandbox Code Playgroud)

或类似的问题,因为“气体巨星是一种行星吗?” 事实上,答案是“是”。也就是说,即便如此,我也会对更改初始化器的原型持谨慎态度;查一下里氏替换原理。基本上,您永远不想处于这样一种情况:某些东西需要 a Planet(实际上可能是子类之一),但只适用于三个类中的某些Planet类,如果传递了不同的类,则破坏。