我遇到以下问题,我想知道是否有一种好的方法可以在不使用多重继承的情况下对这些对象进行建模。 如果有什么区别的话,我正在使用Python。
学生需要联系信息以及学生信息。 成年人需要联系信息和账单信息。 学生可以是成年学生,在这种情况下我需要联系/学生/账单信息,或者他们可以是儿童,在这种情况下我需要联系/学生/家长信息。
只是为了清楚如何使用该系统,我需要能够请求所有成人的列表(我将获得成人学生加上家长),或所有学生的列表(我将获得儿童学生加上家长)成人学生)。
此外,所有这些对象都需要有一个共同的基类。
I have the following problem and I'm wondering if there's a nice way to model these objects without using multiple inheritance. If it makes any difference, I am using Python.
Students need contact information plus student information. Adults need contact information plus billing information. Students can be adult students, in which case I need contact/student/billing info, or they can be children, in which case I need contact/student/parent info.
Just to be clear on how the system will be used, I need to be able to ask for a list of all adults (and I will get adult students plus parents), or a list of all students (and I will get child students plus adult students).
Also, all of these objects need to have a common base class.
发布评论
评论(8)
您所拥有的是角色的示例——通过继承对角色进行建模是一个常见的陷阱,但是角色可以更改,并且不建议更改对象的继承结构(即使在可能的语言中,例如Python)。 孩子们长大成人,一些成年人也将成为儿童学生的父母以及成年学生自己——他们可能会放弃其中一个角色,但需要保留另一个角色(他们的孩子转学,但他们没有转学,反之亦然) 。
只需有一个包含必填字段和可选字段的 Person 类,后者代表角色,可以更改。 “请求列表”(与继承或其他方式完全无关)可以通过动态构建列表(遍历所有对象以检查每个对象是否满足要求)或维护与可能的要求相对应的列表(或频繁查询和临时查询的两种策略的混合)。 某种数据库可能会在这里有所帮助(并且大多数数据库在没有继承的情况下工作得更好;-)。
What you have is an example of Role -- it's a common trap to model Role by inheritance, but Roles can change, and changing an object's inheritance structure (even in languages where it's possible, like Python) is not recommended. Children grow and become adults, and some adults will also be parents of children students as well as adult students themselves -- they might then drop either role but need to keep the other (their child changes schools but they don't, or viceversa).
Just have a class Person with mandatory fields and optional ones, and the latter, representing Roles, can change. "Asking for a list" (quite independently of inheritance or otherwise) can be done either by building the list on the fly (walking through all objects to check for each whether it meets requirements) or maintaining lists corresponding to the possible requirements (or a mix of the two strategies for both frequent and ad-hoc queries). A database of some sort is likely to help here (and most DBs work much better without inheritance in the way;-).
我确信其他人很快就会发表评论(如果他们还没有),一个好的面向对象原则是“优先考虑组合而不是继承”。 从您的描述来看,您似乎违反了单一责任原则,并且应该将功能分解为单独的对象。
我还想到Python支持鸭子打字,这就引出了一个问题“为什么会这样”所有类都有一个共同的基类很重要吗?”
As I'm sure someone else will comment soon (if they haven't already), one good OO principle is "Favor composition over inheritance". From your description, it sounds suspiciously like you're breaking the Single Responsibility Principle, and should be breaking down the functionality into separate objects.
It also occurs to me that Python supports duck typing, which begs the question "Why is it so important that all the classes have a common base class?"
非常简单的解决方案:使用组合而不是继承。 不要让 Student 从 Contact 和 Billing 继承,而是将 Contact 设为 Person 的字段/属性并从中继承。 让计费成为学生的一个领域。 使 Parent 成为 Person 的自引用字段。
Very simple solution: Use composition rather than inheritance. Rather than having Student inherit from Contact and Billing, make Contact a field/attribute of Person and inherit from that. Make Billing a field of Student. Make Parent a self-reference field of Person.
听起来你并不真的需要多重继承。 事实上,您并不真正需要多重继承。 这只是多重继承是否简化了事情的问题(我在这里不认为是这种情况)。
我将创建一个 Person 类,其中包含成人和学生共享的所有代码。 然后,您可以拥有一个 Adult 类,其中包含仅成人所需的所有内容,以及一个 Child 类,其中包含仅儿童所需的代码。
It doesn't sound like you really need multiple inheritance. In fact, you don't ever really need multiple inheritance. It's just a question of whether multiple inheritance simplifies things (which I couldn't see as being the case here).
I would create a Person class that has all the code that the adult and student would share. Then, you can have an Adult class that has all of the things that only the adult needs and a Child class that has the code only the child needs.
这听起来像是可以通过组件架构(例如 zope.components)非常漂亮且灵活地完成的事情。 组件在某种程度上是一种超级灵活的组合模式。
在这种情况下,当您加载数据以根据某些信息在其上设置标记接口时,我可能最终会做一些事情,例如如果年龄> = 18,则设置 IAdult 接口等。然后您可以获取成人信息通过做
或类似的事情。
(编辑:实际上我可能会用来
一次性获取所有模式。:)
组件架构可能有点过头了,但是一旦你习惯了这样的思考,许多问题就会变得微不足道。 :)
查看 Brandons 出色的 PyCon 讨论:http://www.youtube.com/watch ?v=UF77e2TeeQo
我的介绍性博客文章: http://regebro.wordpress .com/2007/11/16/a-python-component-architecture/
This sounds like something that could be done quite nicely and flexibly with a component architecture, like zope.components. Components are in a way a sort of super-flexible composition patterns.
In this case I'd probably end up doing something when you load the data to also set marker interfaces on it depending on some information, like if age >= 18 you set the IAdult interface, etc. You can then get the adult information by doing
or something like that.
(Edit: Actually I'd probably use
to get all schemas in one go. :)
A component architecture may be overkill, but once you got used to thinking like that, many problems get trivial. :)
Check out Brandons excellent PyCon talk about it: http://www.youtube.com/watch?v=UF77e2TeeQo
And my intro blog post: http://regebro.wordpress.com/2007/11/16/a-python-component-architecture/
我认为您的要求过于简单化,因为在实际情况下,您可能会让学生拥有自己的帐户来处理账单,即使他们是需要家长联系信息的未成年人。 此外,您的家长联系信息可能与实际情况中的账单信息不同。 您可能还需要与其他人一起结帐的成年学生。 但是,除此之外 - 根据您的要求,这里有一种方法:
类:Person、BillingInfo、StudentInfo。
所有的人都是 Person 类的实例...
检查字段将允许您根据需要创建列表。
I think your requirements are over-simplified, since in a real situation, you might have students with their own accounts to handle billing even if they are minors who need parent contact information. Also, you might have parental contact information be different from billing information in an actual situation. You might also have adult students with someone else to bill. BUT, that aside - looking at your requirements, here is one way:
classes: Person, BillingInfo, StudentInfo.
All people are instances of class Person...
Checking the fields will allow you to create lists as you desire.
一种解决方案是创建 ContactInfo、StudentInfo 和 BillingInfo 类继承自的 Info 基类/接口。 拥有某种包含 Info 对象列表的 Person 对象,然后您可以使用 ContactInfo、StudentInfo 等填充 Info 对象列表。
One solution is to create a base Info class/interface that the classes ContactInfo, StudentInfo, and BillingInfo inherit from. Have some sort of Person object that contains a list of Info objects, and then you can populate the list of Info objects with ContactInfo, StudentInfo, etc.
在伪代码中,您可以执行以下操作:
然后您可以创建一个名为 StudentManager 的类:
In pseudocode, you could do something like this:
Then you could create a class called StudentManager: