9

次の問題があり、多重継承を使用せずにこれらのオブジェクトをモデル化する良い方法があるかどうか疑問に思っています。違いがあれば、私は Python を使用しています。

学生は、連絡先情報と学生情報が必要です。大人は、連絡先情報と請求情報が必要です。生徒は成人の生徒である可能性があり、連絡先/生徒/請求情報が必要な場合と、子供である可能性がある場合は、連絡先/生徒/保護者の情報が必要な場合があります。

システムがどのように使用されるかを明確にするために、すべての大人のリスト (大人の生徒と保護者を取得します)、またはすべての生徒のリスト (子供の生徒と保護者を取得します) を要求できるようにする必要があります。成人学生)。

また、これらのオブジェクトはすべて、共通の基本クラスを持つ必要があります。

4

8 に答える 8

8

あなたが持っているのはロールの例です-継承によってロールをモデル化するのは一般的なトラップですが、ロールは変更される可能性があり、オブジェクトの継承構造を変更することは (Python などの可能な言語であっても) 推奨されません。子供は成長して大人になり、一部の大人は大人の生徒だけでなく、子供の生徒の親にもなります。その場合、どちらかの役割を放棄する可能性がありますが、もう一方の役割を維持する必要があります (子供は学校を変えるが転校しない、またはその逆)。 .

必須のフィールドとオプションのフィールドを持つクラス Person を用意するだけで、ロールを表す後者は変更できます。「リストの要求」(継承またはその他とはまったく無関係) は、その場でリストを作成する (すべてのオブジェクトを調べて、それぞれが要件を満たしているかどうかを確認する) か、可能な要件 (または頻繁なクエリとアドホック クエリの両方に対する 2 つの戦略の組み合わせ)。ここでは、何らかのデータベースが役立つ可能性があります (そして、ほとんどの DB は、途中で継承がなくてもはるかにうまく機能します;-)。

于 2009-07-15T14:12:30.133 に答える
1

これは、zope.components のようなコンポーネント アーキテクチャを使用して、非常にうまく柔軟に実行できるように思えます。コンポーネントは、ある意味で、一種の非常に柔軟な構成パターンです。

この場合、データを読み込んで、情報に応じてマーカー インターフェイスも設定するときに何かを行うことになるでしょう。たとえば、18 歳以上の場合に IAdult インターフェイスを設定するなどです。やっている

adultschema = IAdultSchema(person)

またはそのようなもの。(編集:実際にはおそらく使用します

queryAdapters(person, ISchema)

一度にすべてのスキーマを取得します。:)

コンポーネント アーキテクチャはやり過ぎかもしれませんが、そのような考え方に慣れると、多くの問題が簡単になります。:)

それについての Brandons の優れた PyCon トークをチェックしてください: http://www.youtube.com/watch?v=UF77e2TeeQo そして、私の紹介ブログ投稿: http://regebro.wordpress.com/2007/11/16/a-python-コンポーネントアーキテクチャ/

于 2009-07-15T14:38:36.550 に答える
1

実際の状況では、保護者の連絡先情報が必要な未成年者であっても、請求を処理するために独自のアカウントを持つ学生がいる可能性があるため、要件は単純化しすぎていると思います。また、実際の状況では、保護者の連絡先情報と請求先情報が異なる場合があります。また、他の誰かに請求する大人の学生がいる場合もあります。しかし、それはさておき-要件を見て、ここに1つの方法があります:

クラス: Person、BillingInfo、StudentInfo。

すべての人はクラス Person のインスタンスです...

class Person:
    # Will have contact fields all people have - or you could split these off into an
    # object.
    parent        # Will be set to None for adults or else point to their parent's
                  # Person object.
    billing_info  # Set to None for non-adults, else to their BillingInfo object.
    student_info  # Set to None for non-student parents, else to their StudentInfo
                  # object. 

フィールドをチェックすると、必要に応じてリストを作成できます。

于 2009-07-15T14:39:31.683 に答える
0

擬似コードでは、次のようなことができます。

Class Student
    Inherits WhateverBase

    Private m_StudentType as EnumStudentTypes 'an enum containing: Adult, Child
    Private m_Billing as Billing
    Private m_Contact as Contact
    Private m_Parent as Parent

    Public Sub Constructor(studentType, billing, contact, parent)
        ...logic to make sure we have the right combination depending on studentType.
        ...throw an exception if we try to assign a a parent to an adult, etc.
        ...maybe you could have seperate constructors, one for each studenttype.             
    End Sub


    Public Property StudentType as EnumStudentTypes
        Get
             Return m_StudentType
        End Get
    End Sub

    Public Property Parent 
        Get 
           ...code to make sure we're using a studentType that has a parent,
           ...and throws an exception if not. Otherwise it returns m_Parent
        End Get
    End Sub


    [more properties]
End Class Student

次に、StudentManagerというクラスを作成できます。

Public Class StudentManager
    Public Function GetAdults(studentCollection(Of Students)) as StudentCollection(Of Students)
        Dim ResultCollection(Of Students)

        ...Loop through studentCollection, adding all students where Student.StudentType=Adult  

        Return ResultCollection
    End Function


    [Other Functions]
End Class

Public Enum StudentType
    Adult=0
    Child=1  
End Enum
于 2009-07-15T14:44:17.773 に答える
0

1つの解決策は、ContactInfo、StudentInfo、およびBillingInfoクラスが継承する基本Infoクラス/インターフェースを作成することです。Infoオブジェクトのリストを含むある種のPersonオブジェクトを用意すると、InfoオブジェクトのリストにContactInfo、StudentInfoなどを入力できます。

于 2009-07-15T14:21:58.420 に答える