Objekte speichern sich selber oder werden gespeichert?



  • Welche Methode ist besser?

    object.save();
    

    oder

    irgendwas.save(object);
    


  • ich finde die zweite methode besser, object muss natürlich ein interface anbieten was von irgendwas verstanden wird

    der vorteil ist das wenn du das ganze mal in einer datenbank, file, ram oder sonst wo speichern willst, packs du das ganze in irgendwas

    irgendwas ist dann spezialiesiert aufs speichern



  • Ich würde speicherobjekt.save(objekt); benutzen oder C++-like speicherobjekt << objekt;

    Vielleicht hilft dir boost::serialization weiter.



  • class object : public saveable
    {
    }
    


  • Ei Ow N'Ju schrieb:

    class object : public saveable
    {
    }
    

    Ne!



  • rüdiger schrieb:

    Ei Ow N'Ju schrieb:

    class object : public saveable
    {
    }
    

    Ne!

    doch. das hat lauter vorteile.



  • Ei Ow N'Ju schrieb:

    class object : public saveable
    {
    }
    

    Troll 😃 👍



  • erkenner schrieb:

    Troll 😃 👍

    nein! jetzt sagt mir doch mal, was daran so schlecht sein soll. ich kann die ganzen sachen, die ich speichern will in listen verwalten und in einem ruck abspeichern. ich abstrahiere vom konkreten "objekt" auf etwas, von dem ich nur die speicherungseigenschaften kenne. das ist gut.



  • glaube ihr redet etwas aneinander vorbei. Das eine schließt das andere ja nicht aus. Im Gegenteil. Siehe Gerard:

    Gerard schrieb:

    object muss natürlich ein interface anbieten was von irgendwas verstanden wird

    Und das ginge zB. mit Veerbung.



  • Und was ist, wenn du z.B. von was anderem erben willst?
    Das ist eine ziemlich schlechte und inflexible Lösung. Das kann man so wunderbar in Java mit Interfaces machen, und so wie das aussieht wird hier versucht genau das in C++ "umzuschreiben". Aber C++ != Java



  • nep schrieb:

    Und was ist, wenn du z.B. von was anderem erben willst?

    dann erbe ich eben auch noch von was anderem? wie du angemerkt hast, ist schließlich c++ != java.

    der zeichentrickbösewicht hat allerdings recht, dass ich ein bisschen am thema vorbei bin.

    eine möglichkeit @topic wäre

    class object
    {
      ...
      std::ostream write( std::ostream & out );
    };
    

    das objekt hat schließlich selbst zu wissen, was es speichern soll. und wenn du dann irgendeine tolle struktur hast, in der du alles speicherst, kannst du der eine ostream-schnittstelle verpassen.



  • Ja dann mach mal schön deine Mehrfachvererbung 😉
    Vererbung passt hier einfach nicht. Punkt.



  • class savable {
       pubic:
       virtual void serialize(serialier&)=0;
    }
    
    class foo : publi savable
    {
    /* serialize impl */
    
    }
    

    ist eine möglichkeit die in c++ praktikabel wäre (da der user dann für seine eigenen klassen auch serialisierungen schreiben kann) - die andere wäre es ne template klasse zu verwenden - die würde aber ned bei basisklassen-casts und polimorphie nicht richtig funktionieren



  • Mit Vererbung wäre ich eher vorsichtig, da man zum einen einen gewissen Overhead einführt und zum anderen weiß ich nicht ob man dadurch nicht mehr ausdrückt, als einem Lieb ist.

    Ich finde den Ansatz von boost::serialization nicht schlecht
    http://boost.org/libs/serialization/doc/index.html

    class gps_position
    {
    private:
        friend class boost::serialization::access;
        // When the class Archive corresponds to an output archive, the
        // & operator is defined similar to <<.  Likewise, when the class Archive
        // is a type of input archive the & operator is defined similar to >>.
        template<class Archive>
        void serialize(Archive & ar, const unsigned int version)
        {
            ar & degrees;
            ar & minutes;
            ar & seconds;
        }
        int degrees;
        int minutes;
        float seconds;
    public:
        gps_position(){};
        gps_position(int d, int m, float s) :
            degrees(d), minutes(m), seconds(s)
        {}
    };
    


  • warum muss ..::access nochmal friend sein?



  • kurzefrage schrieb:

    warum muss ..::access nochmal friend sein?

    Vermutlich weil es auf

    template<class Archive>
        void serialize(Archive & ar, const unsigned int version)
    

    zugreifen will, was in dem Fall private ist. Dürfte aber sicher nichts dagegen sprechen die Methode public zu machen.



  • ar & degrees;
    ar & minutes;
    ar & seconds;
    

    Ja, das ist Boost wie es "leibt und lebt". Unsinnige Operatorenüberladungen um dem nächsten Entwickler, der es lesen muss, eine kleine Überraschung zu bereiten. Wo kämen wir denn hin, wenn wir in Boost irgendwelche Schnittstellen im herkömmlichen Sinne verwenden.

    Ich bin da eher für Gerards Ansatz und würde das Speichern abkoppeln.

    public class Person {
    
        public String getName() {
            // ...
        }
    }
    
    public class PersonSerializer implements Serializer {
    
        private Person person = /* ... */
    
        public void serialize() {
            serialize(person.getName());
        }
    
        // ...
    }
    

    Bietet eben den Vorteil, dass man je nach Datentechnologie eine andere Form der Persistenz wählen kann (z.B: wird man kaum in eine Datenbank serialisieren, sondern eher auf Tabellen abbilden).



  • @boost`rockt:
    Hat aber den Nachteil das ich keine internen Daten abspeichern kann.
    Meine Objekte lasse ich lieber ein Saveable-Interface implementieren. Geladen werden die Objekte durch den Konstruktor.

    In Java könnte man auch private Daten speichern/laden durch Reflexion.

    Aber der boost::serialization-Ansatz ist auch interessant. Aber wieso dann nicht gleich von boost::serialization::access erben und das void serialize()-Interface auf die übliche weise implementieren ?

    Welche Vorteile bringt es einem zu verbergen das die Klasse Serialisation anbietet ?
    In Java werden alle Klasse die Serialisation anbieten gekennzeichnet durch das Interface Serializable.

    Eine andere Möglichkeit in C++ wäre es, eine Klasse einfach den Operator << und >> anzubieten. << heist ja "schreibe in Stream" und >> heist "lese aus Stream".
    Dann braucht man nur noch

    FileStream stream = new FileStream("mein_objekt.dat");
    stream << mein_objekt; // speichern
    
    mein_objekt = new Mein_Objekt(stream); // laden
    


  • @boost`rockt:
    Hat aber den Nachteil das ich keine internen Daten abspeichern kann.
    Meine Objekte lasse ich lieber ein Saveable-Interface implementieren. Geladen werden die Objekte durch den Konstruktor.

    Interne Daten, die im normalen Programmablauf nicht verfügbar sein sollen, benötigt man doch ohnehin nur, wenn man auch Logik in diese Datenklassen verfrachtet und das mach ich ohnehin nicht (siehe z.B: XmlSerializer in .NET, die auch keine internen Daten beachten).



  • boost`rockt schrieb:

    ar & degrees;
    ar & minutes;
    ar & seconds;
    

    Ja, das ist Boost wie es "leibt und lebt". Unsinnige Operatorenüberladungen um dem nächsten Entwickler, der es lesen muss, eine kleine Überraschung zu bereiten. Wo kämen wir denn hin, wenn wir in Boost irgendwelche Schnittstellen im herkömmlichen Sinne verwenden.

    Wer die Funktion nicht versteht, hätte kein Programmierer werden sollen. Wobei die Überladung wirklich ein wenig sinnlos ist in dem Fall.

    Bietet eben den Vorteil, dass man je nach Datentechnologie eine andere Form der Persistenz wählen kann (z.B: wird man kaum in eine Datenbank serialisieren, sondern eher auf Tabellen abbilden).

    Bietet den Vorteil gegenüber welcher Lösung?

    Persistenz ist übrigens mehr als Serialisierung

    DEvent schrieb:

    Aber der boost::serialization-Ansatz ist auch interessant. Aber wieso dann nicht gleich von boost::serialization::access erben und das void serialize()-Interface auf die übliche weise implementieren ?

    weil serialize ein Template ist

    Welche Vorteile bringt es einem zu verbergen das die Klasse Serialisation anbietet ?

    (ot: warum machst du immer ein Leerzeichen vor dem Fragezeichen?)

    Der Java Ansatz ist aus Java-Sicht sicherlich in Ordnung. Aber Vererbung bedeutet im C++-Sinn eben mehr. So fügt man einen vtable der Klasse hinzu etc.

    Da ich keinen Vorteil darin sehe, eine Klasse von einer Serialize-Klasse zu erben, sehe ich kein Sinn darin das zu machen. In C++ geht man mit Vererbung nicht so inflazionär um, wie in .NET oder Java, weil man eben mehr Möglichkeiten hat.

    In Java werden alle Klasse die Serialisation anbieten gekennzeichnet durch das Interface Serializable.

    C++ ist nicht Java und es ist eine schlechte Idee C++ wie Java zu programmieren.

    FileStream stream = new FileStream("mein_objekt.dat");
    stream << mein_objekt; // speichern
    
    mein_objekt = new Mein_Objekt(stream); // laden
    

    *hust*



  • DEvent schrieb:

    Eine andere Möglichkeit in C++ wäre es, eine Klasse einfach den Operator << und >> anzubieten. << heist ja "schreibe in Stream" und >> heist "lese aus Stream".
    Dann braucht man nur noch...

    vielleicht noch den typ davorschreiben vor die objekte und beim lesen anhand des type den richtigen ctor aufrufen.
    und mit den zeigern kanns böse enden. soll man die verfolgen? wenn nein, hat man beim reinladen nen zeiger ins nirvana. wenn ja, sollte man doppelverfolgungen und muß kreise verhindern.


Anmelden zum Antworten