c++ vs. java... was hat zukunft



  • DEvent schrieb:

    Wir haben ja schon festgestellt, das man in Java nur mit Referenzen zu tun hat. Const-Methoden habe ich in Java bis jetzt noch nicht vermisst. Wenn ich eine Methode foo.setXxx(); aufrufe, dann ist doch wohl klar, das sie den internen Status des Objekts verändert. Du hast eher die Sprachen vermischt (C++ und Java) und hast gedacht das Java sich genauso wie C++ verhalten würde.

    Und das Zauberwort in diesem Satz ist "ich". Solange ich der einzige bin, der mit meinen Objekten hantiert, ist alles schön und gut - und ich brauche mich um Const-Correctness nicht zu kümmern. Aber in einem größeren Projekt gibt es auch noch meine Mitarbeiter, die auch mit meinen Klassen arbeiten wollen - und von denen weiß ich im schlimmsten Fall nur, daß sie ein Objekt entgegennehmen und damit arbeiten wollen. (in C++ kann ich mit dem Kollegen aushandeln, daß die entsprechende Methode ein 'const T&' erhält und der Compiler verhindert, daß er irgendwas an meinen Objekten ändert - in Java muß ich darauf vertrauen, daß er keine "verbotene" Methode aufruft).

    Stand nicht ein Spruch in Modern Java Design (oder so): Man sollte eine Klasse immer als immutable designen, es seih den man hat gute Gründe es nicht zu tun. Wenn solche Gründe vorliegen, sollte man zwei Klassen designen, eine immutable und eine mutable.

    Ja, immutable Klassen sind sicher praktisch - nur wie bekomme ich in Java die Verbindung zwischen diesen "zwei Klassen" hin?

    Was ist eigentlich schwer an Objekte kopieren, wenn man Java benutzt?
    - entweder man überschreibt die clone() Methode

    Ich glaube Gregor war es, der meinte, daß eine wirklich brauchbare clone() Methode nicht gerade trivial ist und besser gar nicht angesehen werden sollte (der Thread ist leider zu umfangreich, um den entsprechenden Beitrag wiederzufinden)

    - oder man erstellt einen Copy-Constructor

    Da gilt (vermutlich) das selbe wie für clone() (andernfalls wäre clone() ja trivial lösbar)

    - oder man verwendet ObjectStream
    - oder man verwendet Serialisierung

    Dazu hat mir immer noch niemand erklärt, wozu der Umweg überhaupt notwendig ist.

    Das ist doch in C++ genauso.

    Fast - C++ bietet per Default die Möglichkeit an, Objekte zu kopieren (das äußert sich schon in den impliziten Copy-Ctoren und Zuweisungsoperatoren) und man muß nur eingreifen, wenn das Default-Verhalten nicht ausreicht. Java macht es einem da unnötig schwer.



  • Fast - C++ bietet per Default die Möglichkeit an, Objekte zu kopieren (das äußert sich schon in den impliziten Copy-Ctoren und Zuweisungsoperatoren) und man muß nur eingreifen, wenn das Default-Verhalten nicht ausreicht. Java macht es einem da unnötig schwer.

    Wo bitte macht es Java einem schwerer? Probleme gibts doch nur bei einer tiefen Kopie und da gibt sich Java und C++ nichts.

    Ja, immutable Klassen sind sicher praktisch - nur wie bekomme ich in Java die Verbindung zwischen diesen "zwei Klassen" hin?

    interface PointInterface
    {
        int getX();
        int getY();
    }
    
    final class Point implements PointInterface
    {
        private final x;
        private final y;
        public Point(int x, int y);
        int getX() { return x; }
        int getY() { return y; }
    }
    
    class MutablePoint implements PointInterface
    {
        private x;
        private y;
        public MutablePoint(int x, int y);
        public MutablePoint(PointInterface point) { x = point.getX(); y = point.getY(); }
        int getX() { return x; }
        int getY() { return y; }
        void setX(int x);
        void setY(int y);
    }
    
    //... da PointInterface nur getter hat, ist es const-correct
    PointInterface point = new Point(10, 10);
    
    //... nun hat man eine Kopie von point, die man ändern kann
    m_point = new MutablePoint(point);
    
    //... immer noch const-correct, man kann aber explizit casten, um setter zu benutzen
    PointInterface point = new MutablePoint(10, 10);
    

    Dazu hat mir immer noch niemand erklärt, wozu der Umweg überhaupt notwendig ist.

    Wieso ist das ein Umweg? In Java kommst du fast immer damit aus keine Kopien anzulegen. Eine Kopie von einem Objekt zu machen ist ein extremer Spezialfall und da ist es berechtigt es so explizit wie möglich machen zu müssen. Bei einfachen Klassen hast du sowieso Null Aufwand wenn du Serialisierst/die Streams benutzt.

    Nenn doch mal ein Beispiel, wo Java einem richtige Steine in den Weg legt.

    Fast - C++ bietet per Default die Möglichkeit an, Objekte zu kopieren (das äußert sich schon in den impliziten Copy-Ctoren und Zuweisungsoperatoren) und man muß nur eingreifen, wenn das Default-Verhalten nicht ausreicht. Java macht es einem da unnötig schwer.

    Man kann sagen dass das default-Verhalten von Java eben ist, das man keine Kopien erzeugt. Man muss halt explizit sagen das man eine Kopie will. Das Verhalten finde ich eigentlich recht gut und passend.



  • … Und genau das meinte ich damit, dass Java schwerfällig ist. Natürlich ist das ein guter Code. Aber verdammt, der Programmierer ist doch nicht dafür da, irgendwelchen bescheuerten Boilerplate code zu schreiben. Das soll gefälligst der Compiler für mich übernehmen, während ich als Programmierer mein wertvolles geistiges Potential dafür einsetze, die Logik zu implementieren, anstatt einen Sekretärinnenjob zu machen. Die Aufgabe des Computers ist es doch, mir die Arbeit abzunehmen. Also, da hat Java noch einen weiten Weg zu gehen.

    Abgesehen davon führt das alles doch nur dazu, dass sich die Anzahl der Fehler, die man automatisch in den Code baut, multipliziert. Ich halte es für eines der grundsätzlichen Paradigmen, dass eine gute Sprache dem Programmierer das Codeschreiben so weit wie möglich abnimmt (und das heißt: eben *keinen* Boilerplate code schreiben), um die Fehlerwahrscheinlichkeit zu minimieren. Java tut das Gegenteil.

    (C++ in gewissem Grad auch, aber aus einem sehr unterschiedlichen Grund.)

    => Eine Sprache, die den Programmierer dazu zwingt, solchen Code zu schreiben ist, mit Verlaub, Schrott.



  • Da kann ich mich Konrad nur anschließen - es kann doch nicht angehen, daß ich drei Klassen (PointInterface, Point und MutablePoint) schreiben und untereinander konsistent halten muß, nur um mein Programm const-korrekt zu machen.

    DEvent schrieb:

    Dazu hat mir immer noch niemand erklärt, wozu der Umweg überhaupt notwendig ist.

    Wieso ist das ein Umweg? In Java kommst du fast immer damit aus keine Kopien anzulegen. Eine Kopie von einem Objekt zu machen ist ein extremer Spezialfall und da ist es berechtigt es so explizit wie möglich machen zu müssen. Bei einfachen Klassen hast du sowieso Null Aufwand wenn du Serialisierst/die Streams benutzt.

    Klar habe ich den Aufwand - ich muß überall, wo's benötigt wird, den Read-und-Write-Code einbauen. Und ich muß dafür sorgen, daß meine Klasse serialisierbar wird (klar reicht in vielen Fällen ein "implements serializable" dafür, aber offenbar nicht in allen Fällen).

    Fast - C++ bietet per Default die Möglichkeit an, Objekte zu kopieren (das äußert sich schon in den impliziten Copy-Ctoren und Zuweisungsoperatoren) und man muß nur eingreifen, wenn das Default-Verhalten nicht ausreicht. Java macht es einem da unnötig schwer.

    Man kann sagen dass das default-Verhalten von Java eben ist, das man keine Kopien erzeugt. Man muss halt explizit sagen das man eine Kopie will. Das Verhalten finde ich eigentlich recht gut und passend.

    Aber es ist deutlich schwerer, Java Wert-Semantik beizubringen, als in C++ mit Referenzsemantik zu arbeiten. Und in der Anwendung werden beide Wege gelegentlich benötigt (klar, komplexe Klassen wie ein Auto verwendet man vermutlich besser über Referenzen, aber Hilfsklassen wie int's (da geht's witzigerweise) oder Point (als UDT auf Referenzsemantik festgelegt) sollten auch als Wert verwendet werden können.



  • Bauen wir das Beispiel aus. Ich brauche eine Liste aus Point-Klassen. Dann habe ich Methoden, die diese Liste manipulieren und an einer anderen Stelle will ich diese nur zur Verfügung stellen:

    List pl = new ArrayList();
    pl.add(new MutablePoint(...));
    ...
    
    manipulatePoints(pl);  // hier wird was damit gemacht
    usePoints(pl);         // wie kann ich hier sicher stellen, daß die Objekte nicht verändert werden? Soll ich die jetzt umkopieren oder was?
    

    In C++:

    class Point
    {
        int x;
        int y;
      public:
        void setX(int x_)  { x = x_; }
        void setY(int y_)  { y = y_; }
        int getX() const   { return x; }
        int getY() const   { return y; }
    };
    
    void manipulatePoints(std::vector<Point>& pl)
    {
      pl.at(0).setX(5);  // das ist ok
    }
    
    void usePoints(const std::vector<Point>& pl)
    {
      pl.at(0).setX(5);  // hier meckert schon der Compiler
    }
    

    Und das in nur einer Point-Klasse.



  • DEvent schrieb:

    Probleme gibts doch nur bei einer tiefen Kopie und da gibt sich Java und C++ nichts.

    nicht ganz, in Java ist das erzeugen von tiefen kopien ein kinderspiel. das ist aber auch kein kunststücke, denn die VM hilft einem dabei.

    DEvent schrieb:

    Man kann sagen dass das default-Verhalten von Java eben ist, das man keine Kopien erzeugt. Man muss halt explizit sagen das man eine Kopie will. Das Verhalten finde ich eigentlich recht gut und passend.

    das sehe ich genau so 👍



  • pale dog schrieb:

    DEvent schrieb:

    Probleme gibts doch nur bei einer tiefen Kopie und da gibt sich Java und C++ nichts.

    nicht ganz, in Java ist das erzeugen von tiefen kopien ein kinderspiel. das ist aber auch kein kunststücke, denn die VM hilft einem dabei.

    Wenn du den Umweg über einen Stream und die möglichen Fallstricke bei der Serialisierung ignorierst, vielleicht. In C++ kann ich jeder Klasse genau die Kopier-Semantik geben, die sie benötigt (und normalerweise sollte eine Klasse am besten wissen, was für sie passt), in Java gibt es keine zentrale Anlaufstelle dafür - und dadurch die ganzen Verwirrungen.



  • CStoll schrieb:

    pale dog schrieb:

    DEvent schrieb:

    Probleme gibts doch nur bei einer tiefen Kopie und da gibt sich Java und C++ nichts.

    nicht ganz, in Java ist das erzeugen von tiefen kopien ein kinderspiel. das ist aber auch kein kunststücke, denn die VM hilft einem dabei.

    Wenn du den Umweg über einen Stream und die möglichen Fallstricke bei der Serialisierung ignorierst, vielleicht.

    dafür funktioniert es aber erstaunlich gut.

    CStoll schrieb:

    In C++ kann ich jeder Klasse genau die Kopier-Semantik geben, die sie benötigt (und normalerweise sollte eine Klasse am besten wissen, was für sie passt), in Java gibt es keine zentrale Anlaufstelle dafür - und dadurch die ganzen Verwirrungen.

    nee, die ganzen verwirrungen entstehen, weil du ständig C++ im hinterköpfchen hast. ich glaube du würdest an jeder OO-sprache herumnörgeln, die irgendwelche kleinigkeiten anders macht als C++.
    versuch doch mal, deinen kopf frei zu machen und etwas in Java zu programmieren. ich schätze du würdest dich wundern, wie einfach das geht und wie gut alles zusammenpasst...
    🙂



  • pale dog schrieb:

    CStoll schrieb:

    pale dog schrieb:

    DEvent schrieb:

    Probleme gibts doch nur bei einer tiefen Kopie und da gibt sich Java und C++ nichts.

    nicht ganz, in Java ist das erzeugen von tiefen kopien ein kinderspiel. das ist aber auch kein kunststücke, denn die VM hilft einem dabei.

    Wenn du den Umweg über einen Stream und die möglichen Fallstricke bei der Serialisierung ignorierst, vielleicht.

    dafür funktioniert es aber erstaunlich gut.

    Weil alle Java-Programmierer mit dem Konzept zufrieden sind?
    Randfrage: Wie einfach ist es eigentlich, eine Klasse nachträglich in die Serialisierung einzubauen, bei der der Entwickler (warum auch immer) das "implements serializable" vergessen hat?

    Btw, und wie würdest du das von tntnet angegebene Beispiel (zum Thema const correctness) in Java umsetzen?

    CStoll schrieb:

    In C++ kann ich jeder Klasse genau die Kopier-Semantik geben, die sie benötigt (und normalerweise sollte eine Klasse am besten wissen, was für sie passt), in Java gibt es keine zentrale Anlaufstelle dafür - und dadurch die ganzen Verwirrungen.

    nee, die ganzen verwirrungen entstehen, weil du ständig C++ im hinterköpfchen hast. ich glaube du würdest an jeder OO-sprache herumnörgeln, die irgendwelche kleinigkeiten anders macht als C++.

    Mag ja sein, daß der Umgang mit C++ mein OO-Verständnis verwässert hat. Aber Java ist mir trotzdem zu restriktiv (und - Stichwort "Const Correctness" - teilweise unsicherer als C++).

    versuch doch mal, deinen kopf frei zu machen und etwas in Java zu programmieren. ich schätze du würdest dich wundern, wie einfach das geht und wie gut alles zusammenpasst...
    🙂

    Nur am Rande: die erste Sprache, die ich im Studium beigebracht bekommen habe (nach Basic im Heimversuch und Turbo Pascal während der Schulzeit), war Java. C++ kam erst später, weil ich's fürs Praxissemester benötigt habe. Allerdings sind aus dem Java-Kurs nur Bruchstücke hängen geblieben. (kann auch daran liegen, daß das größte, was ich da bauen "durfte", eine einfach verkettete Liste war)



  • CStoll schrieb:

    Btw, und wie würdest du das von tntnet angegebene Beispiel (zum Thema const correctness) in Java umsetzen?

    in Java würde man interfaces herumreichen. damit kann man methoden gruppieren in z.b. nur-set, nur-get, oder was eben passt. interfaces erlauben eine schärfere trennung als 'const' oder 'nicht-const', ganz im sinne von OOP eben... 😉
    ein anderer weg um (zur laufzeit) sicherzustellen, dass das originalobjekt nicht verändert wird: man erzeugt eine kopie (für den 'Point' ja recht einfach).
    🙂



  • pale dog schrieb:

    ein anderer weg um (zur laufzeit) sicherzustellen, dass das originalobjekt nicht verändert wird: man erzeugt eine kopie (für den 'Point' ja recht einfach).

    Na herzlichen Glückwunsch. Und was ist mit einem Container?! Soll ich den auch kopieren? Das kann nicht dein Ernst sein.

    pale dog schrieb:

    CStoll schrieb:

    Btw, und wie würdest du das von tntnet angegebene Beispiel (zum Thema const correctness) in Java umsetzen?

    in Java würde man interfaces herumreichen. damit kann man methoden gruppieren in z.b. nur-set, nur-get, oder was eben passt. interfaces erlauben eine schärfere trennung als 'const' oder 'nicht-const'

    Und wie schaut das in tntnets Beispiel aus? Bezieh' dich mal bitte direkt darauf. Und zu Interfaces hat sich Konrad ja schon sehr passend geäussert. Es kann nicht sein, dass ich als Programmierer mehr Arbeit mache als der Compiler. Dann kann ich mir auch Assembler antun 😉



  • pale dog schrieb:

    in Java würde man interfaces herumreichen. damit kann man methoden gruppieren in z.b. nur-set, nur-get, oder was eben passt. interfaces erlauben eine schärfere trennung als 'const' oder 'nicht-const', ganz im sinne von OOP eben... 😉
    ein anderer weg um (zur laufzeit) sicherzustellen, dass das originalobjekt nicht verändert wird: man erzeugt eine kopie (für den 'Point' ja recht einfach).
    🙂

    Nichts für ungut, aber es scheint du machst dich entweder ständig über den Begriff 'OOP' lustig, oder dir ist noch nicht ganz so klar was er überhaupt bedeuten soll 😃



  • finix: Ich verstehe Deinen Kommentar nicht. 😞



  • Jester schrieb:

    finix: Ich verstehe Deinen Kommentar nicht. 😞

    Naja, ist nur mein persönlicher Eindruck. Hier dieser "interfaces ... ganz im sinne von OOP eben", zuvor dieses Gewäsch von wegen kopieren in einer "OOP-Sprache"...



  • .filmor schrieb:

    pale dog schrieb:

    CStoll schrieb:

    Btw, und wie würdest du das von tntnet angegebene Beispiel (zum Thema const correctness) in Java umsetzen?

    in Java würde man interfaces herumreichen. damit kann man methoden gruppieren in z.b. nur-set, nur-get, oder was eben passt. interfaces erlauben eine schärfere trennung als 'const' oder 'nicht-const'

    Und wie schaut das in tntnets Beispiel aus? Bezieh' dich mal bitte direkt darauf.

    wie gesagt: interfaces. funktionen, die nichts verändern dürfen, kriegen eine referenz auf das 'nicht_veränderlich'-interface, dann können sie nur methoden aufrufen, die sie dürfen.
    Java hat kein 'const'. sie wollten's mal einbauen, haben's dann aber doch verworfen (die Java-community steht nicht so sehr auf 'feature creep', wie die anhänger der 'andere seite'. 'keep it simple' ist wichtiger). 😉

    .filmor schrieb:

    pale dog schrieb:

    ein anderer weg um (zur laufzeit) sicherzustellen, dass das originalobjekt nicht verändert wird: man erzeugt eine kopie (für den 'Point' ja recht einfach).

    Na herzlichen Glückwunsch. Und was ist mit einem Container?! Soll ich den auch kopieren? Das kann nicht dein Ernst sein.

    nee, natürlich nicht 😉
    nur wundert's mich schon etwas, dass die C++ fans hier ständig ihre copy-ctors und zuweisungsoperatoren in den himmel loben, aber wenn man mal was in Java kopieren will, dann heisst es gleich: 'das ist aber ein mist' 😞

    .filmor schrieb:

    Und zu Interfaces hat sich Konrad ja schon sehr passend geäussert.

    huch? stimmt ja. oha, das hab' ich übersehen. 😮

    .filmor schrieb:

    Es kann nicht sein, dass ich als Programmierer mehr Arbeit mache als der Compiler. Dann kann ich mir auch Assembler antun 😉

    naja, in Java muss man sowieso viel schreiben, das liegt aber meistens an den langen bezeichnern. ausserdem schreibt man 'ne klasse und dazugehörige interfaces nur einmal hin und dann hat man's. ich sehe da kein problem.
    🙂

    finix schrieb:

    Jester schrieb:

    finix: Ich verstehe Deinen Kommentar nicht. 😞

    Naja, ist nur mein persönlicher Eindruck. Hier dieser "interfaces ... ganz im sinne von OOP eben", zuvor dieses Gewäsch von wegen kopieren in einer "OOP-Sprache"...

    oh, tut mir leid 😞
    ich hacke meistens rein, was mir gerade so einfällt, nichts für ungut



  • pale dog schrieb:

    wie gesagt: interfaces. funktionen, die nichts verändern dürfen, kriegen eine referenz auf das 'nicht_veränderlich'-interface, dann können sie nur methoden aufrufen, die sie dürfen.
    Java hat kein 'const'. sie wollten's mal einbauen, haben's dann aber doch verworfen (die Java-community steht nicht so sehr auf 'feature creep', wie die anhänger der 'andere seite'. 'keep it simple' ist wichtiger). 😉

    Nein, MACHT und KONTROLLE sind wichtiger. BUAHAHAHAHA! 😃

    pale dog schrieb:

    .filmor schrieb:

    pale dog schrieb:

    ein anderer weg um (zur laufzeit) sicherzustellen, dass das originalobjekt nicht verändert wird: man erzeugt eine kopie (für den 'Point' ja recht einfach).

    Na herzlichen Glückwunsch. Und was ist mit einem Container?! Soll ich den auch kopieren? Das kann nicht dein Ernst sein.

    nee, natürlich nicht 😉
    nur wundert's mich schon etwas, dass die C++ fans hier ständig ihre copy-ctors und zuweisungsoperatoren in den himmel loben, aber wenn man mal was in Java kopieren will, dann heisst es gleich: 'das ist aber ein mist' 😞

    Das liegt daran, dass man hier nicht Kopieren sollte. Container sind groß und im Allgemeinen nicht trivial zu kopieren. Und genau deshalb sollte man das tunlichst unterlassen, wenn man nicht wirklich einen zweiten Datensatz benötigt (wofür mir so ad hoc keine Anwendung einfällt).

    pale dog schrieb:

    naja, in Java muss man sowieso viel schreiben, das liegt aber meistens an den langen bezeichnern. ausserdem schreibt man 'ne klasse und dazugehörige interfaces nur einmal hin und dann hat man's. ich sehe da kein problem.

    Das Problem liegt in der Wartbarkeit. Wenn du eine Methode zur Klasse hinzufügst musst du an mehreren, eigentlich unabhängigen Stellen im Code Änderungen durchführen. Und jetzt komm mir nicht mit dem "Argument", das seien CnP-Änderungen 😉



  • .filmor schrieb:

    Und jetzt komm mir nicht mit dem "Argument", das seien CnP-Änderungen 😉

    copy&paste 😕
    nö, rechte maustaste -> refactor -> move to interface (oder ähnlich).
    ...aber sowas kennt ihr C++ user ja nicht 😉



  • pale dog schrieb:

    Java hat kein 'const'. sie wollten's mal einbauen, haben's dann aber doch verworfen (die Java-community steht nicht so sehr auf 'feature creep', wie die anhänger der 'andere seite'. 'keep it simple' ist wichtiger). 😉

    Um wieviel simpler ist denn Java mittlerweile noch? 🙂 Aber ja, wenn ich mir das rumgeheule wegen Closures ansehe weiß ich was du meinst 😃



  • pale dog schrieb:

    .filmor schrieb:

    Und jetzt komm mir nicht mit dem "Argument", das seien CnP-Änderungen 😉

    copy&paste 😕
    nö, rechte maustaste -> refactor -> move to interface (oder ähnlich).
    ...aber sowas kennt ihr C++ user ja nicht 😉

    In der Tat. Ich lasse doch keine Skripte an meinem Code arbeiten, soweit kommts noch 😉



  • 50 Seiten. rofl


Anmelden zum Antworten