Objekte speichern sich selber oder werden gespeichert?



  • 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.



  • rüdiger schrieb:

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

    Der Operator macht in diesem Fall einfach keinen Sinn, da man & einfach nicht mit serialisieren in Verbindung bringt, wenn man es nicht weiß. Das hat nichts mit Unwissenheit des Programmierers zu tun. Aber ein derartiger "Fehler" ist in diesem Fall natürlich erlaubt, weil es um boost geht ..

    rüdiger schrieb:

    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

    Genau meine Rede, Persistenz ist mehr als Serialisierung, und darum finde ich, dass eine Datenklasse auch nicht selbst entscheiden soll, welche Form der Persistenz verwendet wird (in deinem Fall eben serialisieren). Daher empfehle ich die Persistierung von der Datenklasse zu trennen um entsprechend Wahlmöglichkeiten zu besitzen, um auch z.B: die Daten auf eine Tabelle in der Datenbank abbzubilden.

    Aber Vererbung bedeutet im C++-Sinn eben mehr. So fügt man einen vtable der Klasse hinzu etc.

    Jetzt bin ich aber gespannt, wie andere Sprachen virtuelle Methoden auflösen, wenn nicht mit einer Art vtable.



  • boost`rockt schrieb:

    rüdiger schrieb:

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

    Der Operator macht in diesem Fall einfach keinen Sinn, da man & einfach nicht mit serialisieren in Verbindung bringt, wenn man es nicht weiß. Das hat nichts mit Unwissenheit des Programmierers zu tun. Aber ein derartiger "Fehler" ist in diesem Fall natürlich erlaubt, weil es um boost geht ..

    Da muss ich dir recht geben. Die Überladung des operator& ist mir unverständlich. Ein << wäre logisch gewesen oder einfach eine funktion serialize.

    rüdiger schrieb:

    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

    Genau meine Rede, Persistenz ist mehr als Serialisierung, und darum finde ich, dass eine Datenklasse auch nicht selbst entscheiden soll, welche Form der Persistenz verwendet wird (in deinem Fall eben serialisieren). Daher empfehle ich die Persistierung von der Datenklasse zu trennen um entsprechend Wahlmöglichkeiten zu besitzen, um auch z.B: die Daten auf eine Tabelle in der Datenbank abbzubilden.

    Wenn ich eine Klasse in eine Datenbank oder eine Textdatei serialisiere, dann ist das immer noch Serialisierung... Und ob ich das in einer Methode der Klasse, zusätzlichen Klasse, globalen Funktion oder wo auch immer mache, das ändert nichts daran und schränkt mich auch nicht in den Möglichkeiten ein, unterschiedlich zu serialisieren.

    Was ich meinte, das Persistenz mehr Dinge umfasst als simple Serialisierung, die Serialisierung ist nur ein Schritt und zwar der einfachste. Folgender Artikel gibt dazu einen schönen Überblick (auch wenn er das Design einer Persistenz-Bib für Common Lisp beschreibt) http://weitz.de/eclm2006/rucksack-eclm2006.txt

    Aber Vererbung bedeutet im C++-Sinn eben mehr. So fügt man einen vtable der Klasse hinzu etc.

    Jetzt bin ich aber gespannt, wie andere Sprachen virtuelle Methoden auflösen, wenn nicht mit einer Art vtable.

    hmm, zB über einen Nachrichten Dispatcher :p Nein, ich verstehe schon was du meinst. Aber da wir hier ja eh gerade von den Unterschieden zwischen Java und C++ reden. Java hat im Grunde immer einen vtable. Aber zum einen kann der JIT virtuelle Funktionen eh besser auflösen, als ein normaler Compiler und zum anderen muss man damit einfach leben, wenn man eine Klasse in Java benutzt.

    In C++ geht man anders vor, da geht man nicht von oben nach unten ("Ich bepack mich mit so viel Last und schau mal was ich dann noch los werde"), sondern von unten nach oben vor ("Ich schleppe nur das, was dringend erforderlich ist").



  • "Ich bepack mich mit so viel Last und schau mal was ich dann noch los werde"

    Naja in Java ist es eben keine Last. Ob ich ein Serializable "implementiere" oder nicht ist eigentlich egal, weil Serializable eh nur eine semantische Sache ist.

    Aber ich weis schon was du meinst 🙂


Anmelden zum Antworten