Post by Seweryn Habdank-WojewódzkiWitam,
Post by Przemek BiernatRainbowColors color = BaseColors::RED
A jaki problem to rozwiazuje? Enum to sa nazwane inty. Jak zaimplementujesz
podwojne dziedziczenie, a potem powrot w diamencie do jednej klasy.
Moim zdaniem poprawne rozwiazanie to uzycie wzorca strategii, a nie biadolenie,
ze C# lub C++ nie maja dziedziczenia po enumach.
Dodatkowo podany przyklad jest bardzo problematyczny z punktu widzenia projektu. Te same problemy ma wiele projektow API dla GUI. Nawarstwiaja sie
kolejne klasy, ktore maja coraz szersze API (bez stosownych interfejsow)
a potem nie mozna w sensowny sposob uzywac wskaznikow na klasy interfejsow.
Poczytaj o strategii.
Pozdrawiam,
Seweryn Habdank-Wojewodzki.
Wiem co to jest wzorzec strategia i jak mniej więcej go stosować choć
tutaj jakoś nie widzę zastosowania, ale może inaczej patrzę na
problem. Dobra podam przykład, takie studium przypadku. Założmy że mam
taką strukturę, będę pisał w C# a raczej w jakimś pseudokodzie żeby
było czytelniej.
class Pojazd
{
public int LiczbaKol { get; set; }
public int Kolor { get; set; }
}
class Samochod : Pojazd
{
public int Pojemnosc { get; set; }
public int LiczbaKoniMech { get; set; }
}
class Rower : Pojazd
{
public int RozmiarObreczy { get; set; }
public int LiczbaPrzelozen { get; set; }
}
i teraz mam listę w której są samochody i rowery
List<Pojazd> lista;
i powiedzmy że mam aplikację klient-serwer na kliencie mam listę i
chcę ją przesłać na serwer w niezmienionej postaci, więc sobie
serializuję binarnie i pakuję przez TcpIp więc:
class Pojazd
{
public virtual void Serialize(BinaryWriter writer)
{
writer.Write(LiczbaKol);
writer.Write(Kolor);
}
public virtual void Load(BinaryReader reader)
{
LiczbaKol = reader.ReadInt32();
Kolor = reader.ReadInt32();
}
}
class Samochod : Pojazd
{
public int Pojemnosc { get; set; }
public int LiczbaKoniMech { get; set; }
public virtual void Serialize(BinaryWriter writer)
{
base.Serialize(writer);
writer.Write(Pojemnosc);
writer.Write(LiczbaKoniMech);
}
public virtual void Load(BinaryReader reader)
{
base.Load(reader);
Pojemnosc = reader.ReadInt32();
LiczbaKoniMech = reader.ReadInt32();
}
}
class Rower : Pojazd
{
public int RozmiarObreczy { get; set; }
public int LiczbaPrzelozen { get; set; }
public virtual void Serialize(BinaryWriter writer)
{
base.Serialize(writer);
writer.Write(RozmiarObreczy);
writer.Write(LiczbaPrzelozen);
}
public virtual void Load(BinaryReader reader)
{
base.Load(reader);
RozmiarObreczy = reader.ReadInt32();
LiczbaPrzelozen = reader.ReadInt32();
}
}
no i dobra jest serializacja i nawet udało się przesłać po sieci po
dwóch stronach mam to samo. Jak sobie zaimplementuję jeszcze oddzielne
klasy potomne po stronie serwera i klienta to nawet mogę mieć różne
zachowanie a dane te same. Ale kurde wyobraźcie sobie że mam jakieś
10-20 propertasów w każdym obiekcie, jak się pomylę w kolejności to
kiszka, dwa razy trzeba pisać i wogóle utrzymanie kłopotliwe, a jak
klas jest sporo to do dupy dwukrotnie. Można by użyć refleksji i
przejechać po property ale w C++ już nie, a powiedzmy że ja nie lubię
reflekcji i chce pisać w C# tak jak w C++ :). No to co trzeba zrobić
property w obiekcie więc:
class Property
{
public string Name;
public abstract object Value { get; set; }
}
class IntProperty : Property
{
private int _value;
public override object Value { get { return _value; } set{ value
= _value as int } }
}
itd...
no i klasa obiektu bazowego
class MyObject
{
Dictionary<int, Property> _properties
public void Serialize(BinaryWriter writer)
{
foreach(KeyValuePair<int, Poperty> pair in _properties)
{
writer.Write(pair.Key);
pair.Value.Serialize(writer);
}
}
// analogicznie dla Load
}
no i konkretny Obiekt
enum PojazdProp
{
PP_LiczbaKol,
PP_Kolor,
}
class Pojazd
{
public int LiczbaKol
{
get {return _properties[(int)PP_LiczbaKol].Value as int }
set { _properties[(int)PP_LiczbaKol].Value = value }
}
itd...
}
No i teraz mój problem polega na tym w słowniku properties muszę użyć
inta a ja chciałbym wpakować tam enuma i jak dojdzie hierarchia
Samochód Rower to wszystko się popieprzy, identyfikatory się pokryją i
będzie kupa, pozatym rzutowanie na inta w tylu miejscach zaciemnia
kod. Może da się sprawę serializacji rozwiązać inaczej ale ja
wymyśliłem takie coś i taką mam architekturę softu. Jedną bibliotekę
dzielę między serwer i klient a zachowanie po dwóch stronach mam
różne :) Oczywiście przykład jest uproszczony bo jeszcze trzeba
rozwiązać sprawę inicjacji properties ( w konstruktorze lub podczas
przypisywania wartości) ale generalnie maszynka działa bo sprawdzałem,
gdyby tylko te enumy dało się rozszerzać byłoby świetnie.