Návrh třídy   zodpovězená otázka

VB.NET, Algoritmy

Mám problém s návrhem třídy, která by pracovala stejně, jako níže uvedená aplikace. Zjednodušeně řečeno potřebuji shromažďovat aplikací vytvořené instance jedné třídy ve vlastnosti (typu Collection) jiné třídy.

Public Class Parent

    'vlastnost do které se mají přidávat instance třídy Child
    Private _Children As New Collection
    Property Children() As Collection
        Get
            Return _Children
        End Get
        Set(ByVal value As Collection)
            _Children = value
        End Set
    End Property

End Class

Public Class Child
    Inherits Parent

    Sub New()
        MyBase.new()
    End Sub

End Class


Module Application

    Sub test()
        'jediná instance třídy Parent
        Dim p As New Parent

        'první instance třídy Child
        Dim c1 As New Child
        p.Children.Add(c1)
        MsgBox(p.Children.Count)

        'druhá instance třídy Child
        Dim c2 As New Child
        p.Children.Add(c2)
        MsgBox(p.Children.Count)

        '...

    End Sub

End Module

Nevím jestli je to vůbec možné, ale rád bych, aby přidávání jednotlivých instancí třídy Child do vlastnosti Children třídy Parent bylo zajištěno již v rámci konstrukce samotných tříd a nikoli až za běhu aplikace, která třídy používá.

Pokoušel jsem se o všechno možné ale nic nefungovalo korektně.

Zkoušel jsem například následující konstruktor třídy Child:

 Sub New()
        MyBase.new()
        MyBase.Children.Add(Me)
    End Sub

Uvedený příklad přidá novou instanci Child do nové instance Parent, což není požadovaný výsledek.

Ani konstruktor, který by vynechal volání konstruktoru rodičovské třídy nefunguje.

Předem děkuji za případné náměty, jak na to.

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Nakonec se ukázalo, že řešením je přiřadit každé instanci Child jeho vlastní instanci Parent přímo v konstruktoru třídy Child. Možná to jde ale řešit lépe. Přidání nové instance do kolekce Children zajišťuje kod aplikace, neboť až v aplikaci se určuje, ke kteréinstanci Parent bude Child přiřazen.

Public Class Parent

    'vlastnost do které se mají přidávat instance třídy Child
    Private _Children As New Collection
    Property Children() As Collection
        Get
            Return _Children
        End Get
        Set(ByVal value As Collection)
            _Children = value
        End Set
    End Property

End Class

Public Class Child
    Inherits Parent

    Private _MyParent As Parent
    Property MyParent() As Parent
        Get
            Return _MyParent
        End Get
        Set(ByVal value As Parent)
            _MyParent = value
        End Set
    End Property

    Sub New(ByVal parent As Parent)
        Me.MyParent = parent
    End Sub

End Class


Module Application

    Sub tester()
        'jediná instance třídy Parent
        Dim p As New Parent

        'první instance třídy Child
        Dim c1 As New Child(p)
        p.Children.Add(c1)
        MsgBox(p.Children.Count)

        'druhá instance třídy Child
        Dim c2 As New Child(p)
        p.Children.Add(c2)
        MsgBox(p.Children.Count)

        '...

    End Sub

End Module

nahlásit spamnahlásit spam 0 odpovědětodpovědět

1. Vytvořte si třídu (třeba ChildrenCollection), která bude dědit z Collection(Of Parent) a overridněte jí metody InsertItem (tam nastavíte nově přidané položkce Parent, pokud už ho bude mít, tak asi vyhoďte výjimku InvalidOperationException, aby náhodou objekt nebyl ve dvou kolekcích najednou) a RemoveItem(tam jí ho odnastavíte).

Chce to vyzkoušet, jestli je potřeba zavolat i ClearItems, nebo jestli zavolá na každou RemoveItem, to nevím a nechce se mi to hledat v dokumentaci.

UpdateItem zakažte, vyhoďte třeba NotSupportedException. Pokud má kolekce dělat tohle, není nutné dovolovat aby někdo mohl na 3. položku přiřadit jiný objekt než tam právě je.

2. Té kolekci dejte v konstruktoru instanci parenta, který ji obsahuje, ať ví, co má vnitřním položkám přiřazovat. Do vlastnosti Children vytvořte novou kolekci v konstruktoru parenta.

3. Jo a jinak tahle hierarchie se typicky řeší pomocí jedné třídy, která má kolekci Children a vlastnost Parent, pokud je to kořen, tak má Parent nastaveno na null. Líp se s tím pracuje a je to odolnější vůči chybě, kdy se někdo pokusí jako kořen udělat třídu Child. Takhle bude kořen automaticky jakýkoliv objekt, který nezařadíte do kolekce. A abyste nemusel kontrolovat, jestli Parent je null, tak si klidně udělejte Boolean readonly vlastnost IsRoot, je to výstižnější.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Díky za tip na řešení. Prakticky jsem použil trochu modifikovanou alternativu řešení, které uvádíte v bodě 3 a funguje to spolehlivě. Každá instance Parent má svoji kolekci Children a jednotlivé instance Parent tak existují nezávisle na sobě.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback