从实例而不是类继承 [Python 3]

Woo*_*dsy 4 python oop inheritance class

我想启动子类的多个实例,每个子类从类的特定实例而不是通用类中获取属性。

例如,如果我有建筑物和房间,则每个房间都需要属于建筑物的特定实例,并采用其属性和方法。

class Building:
     def __init__(self, buildingName, location):
        self.buildingName = buildingName
        self.location = location
        # lots more intersting stuff

    def Evacuate_Building(self):
        # do some stuff
        pass

class Room(Building):
     def __init__(self, roomName, roomType):
        self.roomName = roomName
        self.roomType = roomType
        # lots more intersting stuff

    def Directions(self, Current_Location):
        '''do some stuff involving this.roomName and this.location which comes from the specific instance of the class'''
        pass
Run Code Online (Sandbox Code Playgroud)

假设我有三栋建筑:“北”、“南”和“西”。

每栋楼都有自己的房间。

仅看北楼,它有“N1”、“N2”、“N3”、“N4”房间。

在我的代码中,我将首先遍历并启动三座建筑物,然后我将启动房间,以某种方式将它们链接回其相应的建筑物。

这允许我使用 Directions 方法,该方法利用其父类实例的属性位置,该属性对于该建筑物来说是唯一的,而不是一般值。它还需要能够使用父类 Evacuate_Building 中的方法。

每次我使用 super(buildingName, location) 或 Building.__ init__(self,buildingName, location) 在更标准的设置中启动一个房间时,我可以通过传递位置数据来解决这个问题,但这意味着我必须编写位置每个房间,如果我在建筑物中添加或更改某些内容,如果添加了其他属性,我需要更改每个房间的初始化和初始化代码。

我还可以通过将 Building 的实例作为参数传递给 init,然后使用 this.location =building.location 来复制属性,但这也有与上面相同的问题,而且我不以这种方式获取方法。

我想要某种方式来传递建筑物的特定实例,以便房间继承其特定的属性和方法。

欢迎任何反馈、建议、批评、完全不同的方法!先感谢您!

aba*_*ert 5

你的设计很奇怪。房间不是建筑物,那么为什么要Room继承呢Building1

\n\n

房间和建筑物之间存在一种关系:每个房间都在建筑物中,并且每个建筑物都包含零个或多个房间。您可以通过组合\xe2\x80\x94 来表示任关系或两者,即通过添加成员:

\n\n
class Room:\n    def __init__(self, building, roomName, roomType):\n        self.building = building\n        self.roomName = roomName\n        self.roomType = roomType\n        # lots more intersting stuff\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者:

\n\n
class Building:\n    def __init__(self, buildingName, location):\n        self.buildingName = buildingName\n        self.location = location\n        self.rooms = set()\n    def add(self, room):\n        self.rooms.add(room)\n
Run Code Online (Sandbox Code Playgroud)\n\n

Room.__init__如果你愿意的话,你甚至可以打电话building.add(self)

\n\n
\n\n

请注意,这正是您想要的:每个都Room与特定Building实例相关,self.building而不是与Building类相关。

\n\n

因此,您不必为每个实例编写位置Room,只需将相同的Building实例传递给所有实例即可。如果我在 中添加或更改某些内容BuildingRoom该建筑物中的每个人都会看到其中的更改,self.building而无需重复自己或做任何特殊的事情。

\n\n

甚至不仅仅是静态地存在于代码中。您可以Building在运行时使用移动 a self.location = new_location。那么,对于Room其中的每一个Buildingself.building.location就是现在new_location

\n\n
\n\n

另外,您通常不希望 aRoom支持 a 的方法Building。调用Evacuate_BuildingaRoom没有多大意义。打电话Evacuate_Room可能。在这种情况下你Building可能会这样做:

\n\n
def Evacuate_Building(self):\n    for room in self.rooms:\n        room.Evacuate_Room()\n
Run Code Online (Sandbox Code Playgroud)\n\n

但是,如果您发现房间Room着火,因此需要疏散整个房间BuildingRoom包括所有房间,该怎么办?简单:您撤出 的Room属性building

\n\n
if is_on_fire(room):\n    room.building.Evacutate_Building()\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

1. 这就是继承的含义:class Room(Building):表示anyRoom是一个Building。或者,换句话说:任何想要 aBuilding并得到 a 的代码Room都会对此感到满意。有时有理由颠覆这个含义(例如,mixin 类只是一大堆方法实现;如果你写class Skyscraper(Building, MajorConstructionMixin):,你并没有真正声明 aSkyscraper是 a MajorConstructionMixin,因为这实际上没有任何意义;你只是借用一些方便的实现代码)\xe2\x80\x94但这仍然是你正在颠覆的意义。

\n\n

2. 请注意,如果在两个方向上添加引用,则会出现引用循环。这并不违法,甚至通常不是一个问题;它只是意味着当你放弃一座建筑物及其所有房间时,CPython 垃圾收集器不会找到它们并立即删除它们,直到收集器下次运行。不过,虽然这不是什么大问题,但大多数程序不需要双向关系,因此您应该看看是否可以通过消除一个关系来简化您的设计。

\n