嵌套或扁平的类结构?

时间:2015-09-05 21:28:13

标签: python oop

我想将物理系统及其层次结构的表示实现到类结构中。互联网上的许多例子都提出了这种方法:

sport = Sport()
soccer = sport.GetSoccer()
ball = soccer.GetBall()
ball.Kick()

但是,我觉得以下内容会更容易使用:

sport = Sport()
sport.soccer.ball.Kick()

是否有选择前者的标准或惯例?

修改

关于BrianOBorodin的答案,我应提供另一个例子,而不是足球和运动,这不能代表我的实际需要。

真正的上下文是一个嵌入式设备,即 ASIMO,通过用C编写的API进行接口。该API由数千个不按层次组织的函数组成。

我的目标是实现一种ORM(我不知道这个的正确术语),它带来了这些功能的分层访问。

换句话说,如果我想移动机器人左臂的中指,我可能会用这样的模糊参数调用一个模糊的函数:

_dll.asimo_arm_left_hand_move_finger(2, 1, 3, 2, 4)

更好的方法是提供类似以下内容的OOP解决方案:

asimo.arms.left.hand.middleFinger.join[1].ApplyTorque(2) # [nNm]

这种方法可以帮助用户在交互式控制台中与机器人进行通信,并获得自动完成所提供的所有好处。

请注意,asimo认为只是一个例子;我不是在和机器人一起工作。

1 个答案:

答案 0 :(得分:3)

值得庆幸的是,没有任何标准或惯例可供选择,因为每个标准或惯例都是体育运动,运动中使用的东西,以及对此类事物采取的行动。这类实体不会构成一个" is-a"层次结构。足球不是一种足球;踢不是一种球。 Kick应该是一个班级吗?!那个疯狂/错误。常识应该告诉你它是一种某种东西的方法,虽然可能不是一个球(更合理的,一种Player类的方法,适用于{{1参数)。

通过更多考虑这一点,请记住,继承(is-a,包含)和包含(has-a,成员资格)虽然是互补的建模工具,但却是截然不同的。

编辑后添加:

感谢您解释更多您的实际问题。你有一个有趣和具有挑战性的问题,分为两部分,只有你在这里要问的第一部分:(*)如何正确建模你的小玩意,子系统,子组件及其部分的层次结构; (**)如何建立该模型与数千个函数的平面API之间的对应关系。

我喜欢你的想法:与具有1000多个随机组织的函数的API相比,具有自动完成功能的交互式控制台在具有直观正确的对象层次结构时提供了更好的用户体验。 (理想情况下,动态图形用户界面具有速度敏感型触摸屏......但明年也可能。)

您的用户最终会输入Ball等虚线表达式。在各个方面,这种关系有时会是"是-a" (子类),和其他时间" has-a" (是属性)。你的问题显然太大了,也许是专有的,因为你要发布完整的细节,所以很难提供更有针对性的建议。

投机模糊的一般性:

无论如何,您可以做出选择。您的陈述应该受到影响,但不是由您定位的API决定的:您不希望让自己比现有的更难。

假设您的设备是汽车,标准的4轮,4灯,2轴对称,引擎等。如果API提供单独的功能,可以在前轮和后轮上运行,那么你可能想要this.that.type_of_that.part_of_that.sub_part.left_corner.apply_force(3500)对象的wheels属性是一个带有字段Carfront的命名元组,每个属性又是一个WheelPair对象,带有属性(成员){{ 1}}和rear,它们是Wheel对象。如果left是Car对象,那么right将是一个Wheel,它可能具有car属性,浮点值(以及API提供的不同单位的其他属性)。< / p>

但是,如果API具有作用于所有轮子的功能,而其他只作用于一个轮子的功能,那么之前的表示可能很笨拙,您可能更喜欢更平坦的 - 比如,带有字段的命名元组{ {1}},其每个元素都是一个轮子。这样您就可以通过人性化的名称和索引号来访问每个轮子,同时还允许您遍历4元组的轮子。

虽然上一个示例并非完全来自您的问题域,但您很可能会遇到类似的决定。前后车轮推荐的PSI 通常不同,汽车的广泛API可能反映了这一点;但如果它没有,你也不必。不要比问题需要更嵌套!