Windowsprogramm mit C++ oder Java?
-
Ich finde Operator-Überladung sehr wichtig, da es die Ausdrucksweise des Codes stärkt. Unter a + b kann ich mir etwas vorstellen. Sicher gibt es Leute die dazu tendieren die Operator-Überladung zu missbrauchen und Operatoren für allen scheiß zu überladen. Aber deswegen ist Operator-Überladung nicht schlecht. Wie gesagt, es soll ein mittel sein um die Ausdrucksstärke (und damit die Lesbarkeit) des Codes zu erhöhen.
Ich habe nie behauptet das ich Operatorüberladung schlecht finde. Ich habe nur gesagt das man zu 99% Operatorüberladung nicht benötigt und man damit viel Misst machen kann. Das wird eben in Java Rechnung getragen und das finde ich gut.
Das Argument ist aber nicht sehr stark.
Ich nehme mal an, dass du ein Gegner der ungarischen Notation (im Sinne von Typen in Variablennamen einzubauen) bist und du das u.a. damit begründest, dass man Dank Intelli-Sense sowieso jederzeit weiß was für ein Typ ein Objekt hat.
Es gibt nur eine Hand voll von built-in Typen, somit lässt sich dank Intelli-Sense sehr leicht feststellen ob das Objekt ein built-in Typ ist oder ob es sich um ein Methodenaufruf handelt.Ich bin tatsächlich ein Gegner der UN, aber aus dem einfachen Grund das man nicht zwischen einem Typ zu unterscheiden braucht. Ob etwas eine Realzahl, eine Klasse oder Bool ist, ist vollkommen egal und sollte aus dem Contex ersichtlich sein.
Die Möglichkeit Objekte wie Funktionen zu behandeln durch ein Überladen von dem ()-Operator ermöglicht es in Templates nicht nur Funktionen als Parameter sondern auch Objekte zu verwenden.
In einer OO-Sprache benötigt man eigentlich nur Objekte und würde mit Interfaces oder mit abstrakten Klassen hantieren. Also wenn man Funktionen aus der Sprache weglässt, ist der Operator() unnötig. So gesehen ist die Möglichkeit den Operator() zu überladen in C++ einfach nötig für die Brücke OOP und prozedurale Programmierung.
Oder mit den Worten aus dem Openbook: http://www.galileocomputing.de/openbook/csharp/kap25.htm
Es ist nicht möglich, Operatoren für den Mitgliedszugriff, für den Mitgliedsaufruf (Funktionsaufruf) oder die Operatoren +, &&, ||, ?: oder new zu überladen. Dies geschieht im Namen der Einfachheit. Obwohl mit der Überladung lustige Dinge angestellt werden können, wird die Verständlichkeit des Codes doch erheblich herabgesetzt, da der Programmierer stets daran denken muss, dass der Mitgliedsaufruf (beispielsweise) zu besonderen Operationen führen kann1 . Der Operator new kann nicht überladen werden, da die .NET-Laufzeitumgebung für die Speicherverwaltung zuständig ist, und im C#-Dialekt bedeutet new »Gib mir eine neue Instanz von«.
Es ist darüber hinaus nicht möglich, die zusammengesetzten Zuweisungsoperatoren +=, *= usw. zu überladen, da diese immer in die einfache Operation und eine Zuordnung erweitert werden. Auf diese Weise wird vermieden, dass nur einer der Operatoren definiert wird oder (schauder) dass die Operatoren mit unterschiedlichen Bedeutungen definiert werden.
Das letztere kann man übrigens in C++ ohne weiteres machen.
-
[****&/%&$")(/@*** !!!! Gerade ausführlich geschrieben und dann per short cut direkt Fenster geschlossen !!]
Hi DEvent,
ich will keinen Krieg vom Zaun brechen, aber Dir trotzdem sanft widersprechen (im Sinne eines hilfreichen Gedankenaustauschs)
DEvent schrieb:
...man damit viel Misst machen kann. Das wird eben in Java Rechnung getragen und das finde ich gut....
Ersteres sehe ich auch so, Zweiteres nicht.
Ich selbst habe am Anfang viel mit Operatorüberladung falsch gemacht ... aber wenn ich mir reale Software ansehe, muss ich schon sagen, dass das (bei wirklich für Wiederverwendung ausgelegter Software) ziemlich selten ist.
Hier hat man IMO "das Kind mit dem ade ausgeschüttet" und wegen eher schwacher Nachteile ernstzunehmende Vorteile bzgl Lesbarkeit (z.B. bei eigenen "Zahlklassen") und Generizität über Bord geworfen, z.B.:DEvent schrieb:
...das man nicht zwischen einem Typ zu unterscheiden braucht. Ob etwas eine Realzahl, eine Klasse oder Bool ist, ist vollkommen egal .......
Dem stimme ich zu ... und gerade deswegen bedauere ich die Streichung der Operatorüberladung, weil sie diesem Grundsatz widerspricht; schließlich kann man in Java primitive Typen nur, Klassen hingegen NIE mit Operatoren "bearbeiten". Ich muss also zumindestens zwischen diesen immer unterscheiden.
(Damit will ich nicht der UN das Wort reden - die lehne ich aus demselben Grund ab wie Du)DEvent schrieb:
...In einer OO-Sprache benötigt man eigentlich nur Objekte ...
Eine Sprache, die diesen Grundsatz umsetzt, zwingt aber allen Programmierern in bestimmten Situationen ein unpassendes/ungeschicktes Design oder eingeschränkte Wiederverwendbarkeit (z.B. indem man Sortieralgorithmus an den Container oder den Datentyp koppelt) auf. Es gibt in der Realität einfach Zusammenhänge, die besser prozedural abgebildet werden (z.B. alles, was in Algorithmen formuliert wird; Sortieren, Suchen, krytographische Operationen, ...).
Ich kann verstehen, dass der Bann von Funktionen damals Teil des "didaktischen Konzepts zu Stärkung der OO-Denke" war - aber letztlich ist es IMO eine Verarmung der Sprache und eine Begünstigung schlechten Designs in bestimmten Zusammenhängen (Nach Java-Denke also eigentlich auszumerzen - schließlich ist schlechtes Design viel öfter Ursache für schlechte Programme als Operatorenoverloading ........ ich weiß, dass ich das hier überstrapaziere - ist nicht wirklich erst gemeint).
Übrigens: Den Java-Ansatz "Was zuviel Probleme/Verwirrung/Fehler/... verursacht, kommt nicht in die Sprache", finde ich gut und in vielen Bereichen von Java ach gut umgesetzt ... aber eben bei "Operatorenüberladung" und "Funktionenrausschmiss" eben nicht.
Gruß,
Simon2.
-
Im JDK 7 gibst Operatorüberladung wenigstens für die Klasse BigDecimal.
btw Mir ist ne Möglichkeit die ich nicht nutze lieber als ne Möglichkeit die ich brauche.
-
Zeus schrieb:
...
btw Mir ist ne Möglichkeit die ich nicht nutze lieber als ne Möglichkeit die ich brauche.Mir auch - aber wenn Du viel mit "fremden Code" arbeiten musst, dann sind Dir vielleicht auch Features, die man nicht mißbrauchen kann, wichtiger ... ideal wäre eine Art "Skillfreischaltung": Anfänger bekommen erstmal ein paar Features an die Hand und im Laufe der Zeit erwirbt der Programmierer "Zertifikate", mit denen er weitere Features "freischaltet"....
(Und dann steht über de Sourcecode automatisch "Dieser Code kann nur von Programmiereren der Skillstufe 6 verstanden und nur mit Skillstufe 8 verändert werden")Gruß,
Simon2.
-
Zeus schrieb:
Im JDK 7 gibst Operatorüberladung wenigstens für die Klasse BigDecimal.
Ist mir neu. Woher hast Du das? Was kommt alles noch mit Java 7?
-
Naja ich bezieh mich auf paar Präsentationen,
http://www.tutego.com/java/jdk7-Java-SE-7.htmallerdings hab ich keine Arhnung, was wirklich dann released.
Bevor ich alles aufliste, stöbert mal selbst auf der Seite ^^
-
Gerade ausführlich geschrieben und dann per short cut direkt Fenster geschlossen !!]
Das ist schade.
ich will keinen Krieg vom Zaun brechen, aber Dir trotzdem sanft widersprechen (im Sinne eines hilfreichen Gedankenaustauschs)
Krieg ist wohl ein wenig übertrieben
Dem stimme ich zu ... und gerade deswegen bedauere ich die Streichung der Operatorüberladung, weil sie diesem Grundsatz widerspricht; schließlich kann man in Java primitive Typen nur, Klassen hingegen NIE mit Operatoren "bearbeiten". Ich muss also zumindestens zwischen diesen immer unterscheiden.
(Damit will ich nicht der UN das Wort reden - die lehne ich aus demselben Grund ab wie Du)Bei Java hat man aber den Unterschied eh immer. Somit finde ich es gut das man diesen Unterschied so deutlich wie möglich macht und Operatoren nur für primitive Datentypen erlaubt. Operatorüberladung in Java würde nur diesen Unterschied verwischen (kaschieren), aber er würde trotzdem immer da sein.
In C++ ist, auch wegen der Templates, der Unterschied deutlich geringer, denn da Objekte und Primitiven gleicher behandelt. Man kann in C++ primitive genauso wie Objekte in Containern speichern, man kann beide per Referenz übergeben, usw.
Eine Sprache, die diesen Grundsatz umsetzt, zwingt aber allen Programmierern in bestimmten Situationen ein unpassendes/ungeschicktes Design oder eingeschränkte Wiederverwendbarkeit
Ich habe bis jetzt noch nie Begriffe "eingeschränkte Wiederverwendbarkeit" und "OOP" in einem Satz gehört
z.B. indem man Sortieralgorithmus an den Container oder den Datentyp koppelt
Gibts dafür ein Beispiel? Man kann in Java ein Sortieralgo Container- und Datentypunabhängig schreiben. Solange der Container die grundlegenden Methoden für einen Sortieralgo anbietet, also Zugriff auf jedes Element, die Elemente zu vergleichen und die Möglichkeit ein Element zu verschieben, ist es einem Sortieralgo egal, ob es eine Liste, ein Baum oder ein Array ist.
Es gibt in der Realität einfach Zusammenhänge, die besser prozedural abgebildet werden
In OO-Sprachen kannst du gerne prozedural Programmieren.
class Fooo { public Fooo(parameter) { schritt_1(); } public void schritt_1() { schritt_2(); } public void schritt_2() { schritt_3(); } }
OOP bietet sogar eine wesentlichen Voreil für prozedurale Programmierung: Jeder Algo hat seine eigene Umgebungvariablen, die abgeschlossen nach Ausen hin sind. So gesehen ist dann jedes Objekt eine eigene Maschine, in der der Algo abgeschirmt von anderen Prozessen ist.
Ich kann verstehen, dass der Bann von Funktionen damals Teil des "didaktischen Konzepts zu Stärkung der OO-Denke" war
Du kannst auch gerne "pure" Funktionen in OOP haben:
class Funktion { public Function(parameter) { this.parameter = parameter; } public value fooo() { return mach_was_mit_den_paramtern(); } } // ... xxx = new Function(parameter).fooo();
aber wenn ich mir reale Software ansehe, muss ich schon sagen, dass das (bei wirklich für Wiederverwendung ausgelegter Software) ziemlich selten ist.
Verrate mir bitte, wo es den wirklich Sinn macht eigene Operatoren zu haben, bis auf mathematische, strings- und vllt. Containern-Klassen. Wobei bei letzteren zwei doch eh nur der + Operator Sinn macht.
Btw, wenn ich den Operator== überlade, wie kann ich dann noch auf Gleichheit und Identität prüfen?
Fooo x, y; x = new Fooo(300); y = new Fooo(300); // x ist zwar gleich mit y, aber nicht identisch if ( x == y ) ...
-
DEvent schrieb:
Btw, wenn ich den Operator== überlade, wie kann ich dann noch auf Gleichheit und Identität prüfen?
Fooo x, y; x = new Fooo(300); y = new Fooo(300); // x ist zwar gleich mit y, aber nicht identisch if ( x == y ) ...
So:
Fooo x, y; x = new Fooo(300); y = new Fooo(300); if ( x == y ) ... //Test nach Gleichheit if(&x == &y) //Test nach Identität
Felix
EDIT: Wenn deine Frage auf Java bezogen war (was ich daran gemerkt habe, dass die * für Zeiger im Zusammenhang mit new fehlen) dann geht es wahrscheinlich nicht...
In Python gibt es dafür aber extra ein eigenes Konstrukt (da sind auch alle Variablen Referenzen, das ganze ist da allerdings IMO konsequenter umgesetzt als in Java, da das auch für primitive Typen gilt...)
Da gibt es dann
if x == y:
passund
if x is y:
pass
-
Was ist wenn man jetzt den Operator& auch noch überläd?
-
Nun ja, wieso willst du den uberladen.
Normalerweise willst du doch nur die Operatorenüberladen, die deine Klassen intuitiv Benutztbar machen, allerdings nur paar Operatoren überladbar zumachen ist wiederrum nicht sehr inkonsequent.
-
DEvent schrieb:
Was ist wenn man jetzt den Operator& auch noch überläd?
dann nimmt man boost::adress_of
-
Zeus schrieb:
Nun ja, wieso willst du den uberladen.
Normalerweise willst du doch nur die Operatorenüberladen, die deine Klassen intuitiv Benutztbar machen, allerdings nur paar Operatoren überladbar zumachen ist wiederrum nicht sehr inkonsequent.
Ist eigentlich dann C# als Sprache konsequenter als C++?
-
In Bezug auf was? :o
-
Zeus schrieb:
In Bezug auf was? :o
Dacht es wäre klar...
In C# kannst du nicht einzelne Operatoren überladen, z.B. musst du, wenn du den operator== überlädst, auch den operator!= überladen.
-
Hi DEvent,
sorry, hat ein wenig gedauert - aber jetzt:
DEvent schrieb:
...
ich will keinen Krieg vom Zaun brechen, aber Dir trotzdem sanft widersprechen (im Sinne eines hilfreichen Gedankenaustauschs)
Krieg ist wohl ein wenig übertrieben
...
Nicht, wenn man den Verlauf einiger "Diskussion" zu ähnlichen Themen hier ansieht.
DEvent schrieb:
...Bei Java hat man aber den Unterschied eh immer....
Eben - finde ich einfach nicht gut und auch inkonsistent.
Schränkt letztlich gerade bei der "Templateschreibung" ein.
(Würde mir wünschen, dass man in C++ auch von ints ableiten könnte)DEvent schrieb:
...Gibts dafür ein Beispiel? Man kann in Java ein Sortieralgo Container- und Datentypunabhängig schreiben. ...
Echt ? Habe ich noch nicht gesehen - bin aber auch nicht die Oberkoryphäe in Sachen Java. Ich habe immer nur Containermethoden zum Suchen oder Sortieren gesehen.
DEvent schrieb:
...In OO-Sprachen kannst du gerne prozedural Programmieren.
class Fooo { public Fooo(parameter) { schritt_1(); } public void schritt_1() { schritt_2(); } public void schritt_2() { schritt_3(); } }
...
Äh, das ist auch nicht das Beispiel für eine "Prozedur", denn hier geht es offensichtlich um eine "Statusmaschine", die von Aufrufer bedient wird (einen Sortieralgo würdest Du doch auch nicht so umsetzen, oder ?). Wenn schon, dann wäre das passende Beispiel (hast Du unten schon ählich selbst genannt):
class Fooo { public Fooo(parameter) { schritt_1(); schritt_2(); schritt_3(); schritt_4(); schritt_5(); schritt_6(); } }
Und da sehe ich zum Einen nix "OO-iges", außer dass man eine "class ..." um seine Funktionssammlung geschrieben hat und zum Anderen ist es IMO ein typisches Beispiel für "unnötiger Userverwirrung": Bei einem Objekt muss ich davon ausgehen, dass es später noch existiert und dass es einen "Lebenszyklus" mit Status hat.... damit stellt sich z.B. beim Such-Objekt die Frage, was der Unterschied ist, ob ich erst Objekt A oder erst Objekt B suche.
DEvent schrieb:
...
class Funktion { public Function(parameter) { this.parameter = parameter; } public value fooo() { return mach_was_mit_den_paramtern(); } } // ... xxx = new Function(parameter).fooo();
Hmmm schön klingendes Beispiel - jetzt variiere ich es mal ein wenig:
class MAC { public MAC(parameter) { this.parameter = parameter; } public value fooo() { return parameter; } } // ... MAC myMAC = new Function(parameter); myMAC.fooo();
Vollkommen gültig und sieht auch erstmal sinnvoll aus ... und trotzdem irgendwie sinnfrei.
Mit einer "freien Funktion" wäre das nicht passiert.WENN man ein "Gedächtnis"/"Status" (von Dir "Umgebungsvariablen" genannt), hat man es gar nicht mit einem der Problemstellungen zu tun, von denen ich rede ! Und da ist ein Objekt sicher eine gute Sache. Ich rede wirklich von "Algorithmen": Also ein Tier, das nach einmal auf ein Ding losgelassen wird und danach mit allem abgeschlossen hat.
Ich will nicht sagen, dass ALLE Probleme so sind (und OO deswegen überflüssig wäre), sondern nur, dass es eben auch solche gibt - und das für die ein OO-Ansatz IMO schlechteres Design ist als ein prozeduraler.DEvent schrieb:
...
Btw, wenn ich den Operator== überlade, wie kann ich dann noch auf Gleichheit und Identität prüfen?Fooo x, y; x = new Fooo(300); y = new Fooo(300); // x ist zwar gleich mit y, aber nicht identisch if ( x == y ) ...
Ganz einfach: Mit dem operator==() !
Fooo ist offensichtlich eine "Pointerklasse" und wenn der operator==() überladen ist, dann drückt sie aus, dass 2 Fooos genau dann identisch sind, wenn der operator==() das so sieht. Du hast jetzt keine Implementation dabeigepackt, aber vermutlich schwebte Dir so etwas wie ein Attribut-Vergleich vor.
Diese Identität ist z.B. bei reinen Value-Typen sinnvoll. Du unterscheidest auch nicht zwischen 2 verschiedenen "3en", sondern 3 ist eben 3.
Oder ein anderes Beispiel: Wenn man so eine Art "Singletons" baut: Es soll zu jedem Initialisierungswert nur ein Objekt geben - new wird noch geeignet überladen, dass es in der Tabelle bereits instantiierter Objekte nachsieht und nur die Adresse des bvereits bestehenden zurückgibt.Das Überladen eines operators ist einfach eine Designentscheidung, mit der man seiner Klasse bestimmte Eigenschaften mitgibt - und da sind eigene operatoren mächtige Mittel, die ich nicht missen möchte...
Gruß,
Simon2.
-
WENN man ein "Gedächtnis"/"Status" (von Dir "Umgebungsvariablen" genannt), hat man es gar nicht mit einem der Problemstellungen zu tun, von denen ich rede ! Und da ist ein Objekt sicher eine gute Sache. Ich rede wirklich von "Algorithmen": Also ein Tier, das nach einmal auf ein Ding losgelassen wird und danach mit allem abgeschlossen hat.
Ich will nicht sagen, dass ALLE Probleme so sind (und OO deswegen überflüssig wäre), sondern nur, dass es eben auch solche gibt - und das für die ein OO-Ansatz IMO schlechteres Design ist als ein prozeduraler.class Tier { public Tier(initalisationsParameter) { } public void run() { Algorithmus wird gestartet wenn Algorithmus zuende, informiere alle Oberserver } public void addObserver(Observer o); } //... Tier tier = new Tier(anfangsparameter); tier.addObserver(this); tier.run(); //... tier.run(); //... tier.run();
Was spricht gegen sowas? Solange die Anfangsparameter germerkt werden, kann man den Algorithmus "Tier" immer wieder laufen lassen und wenn er ferdig ist, wird ein Observer benachrichtigt, und ist danach "mit allem abgeschlosen". Wenn man andere Anfangsparameter haben will, erstellt man sich ein neues "Tier", oder man baut sich eine setAnfangsparameter() ein.
Vollkommen gültig und sieht auch erstmal sinnvoll aus ... und trotzdem irgendwie sinnfrei.
Mit einer "freien Funktion" wäre das nicht passiert.Ach echt?
fooo meineFunktion(parameter) { return parameter; } //.. meineFunktion(xxxxx);
Versteh irgendwie nicht warauf du hinaus willst?
Das Überladen eines operators ist einfach eine Designentscheidung, mit der man seiner Klasse bestimmte Eigenschaften mitgibt - und da sind eigene operatoren mächtige Mittel, die ich nicht missen möchte...
Inzwischen sehe ich das eigentlich genauso...
-
DEvent schrieb:
...
Was spricht gegen sowas? ...Nichts - nur, dass ich offenbar noch nicht klar gemacht habe, worauf ich eigentlich hinaus will, denn Du bringst immer wieder Beispiele an, wo ein Objekt die beste Designwahl ist und ich das auch so machen würde.
"run" ist einfach gut als Eigenschaft/Fähigkeit einer Klasse zu modellieren und das Benachrichtigen von Observern auch.Mir geht es aber darum, dass es eben auch Dinge gibt, bei denen das NICHT so einfach geht. Nehmen wir z.B. das Verschlüsseln eines Textes: Wessen Eigenschaft ist das ? Des Schlüssels ? Des Textes ? ...
Das geht IMO an eindeutigsten mit einer freien Funktion.DEvent schrieb:
...
Vollkommen gültig und sieht auch erstmal sinnvoll aus ... und trotzdem irgendwie sinnfrei.
Mit einer "freien Funktion" wäre das nicht passiert.Ach echt?
fooo meineFunktion(parameter) { return parameter; } //.. meineFunktion(xxxxx);
Versteh irgendwie nicht warauf du hinaus willst?
...Tut mir leid, ich glaube, ich muss das wirklich besser ausdrücken.
Für mich besteht der Unterschied zwischenFooo myFooo; myFooo.meineFunktion(parameter) { return parameter; }
und
meineFunktion(parameter);
darin, dass mir bei der zweiten Variante bewusst ist, dass ich höchstens den Zustand von "parameter" verändert habe (und dementsprechend ein identischer Aufruf exakt denselben Effekt hat).
Oder mal von der Programmiererintention gesprochen: "Ich tue etwas mit parameter".Bei der ersten Variante "tue ich etwas mit myFooo" (evtl. auch mit parameter). Der innere Zustand von myFooo spielt in das Ergebnis mit rein und ich kann NICHT davon ausgehen, dass ein identischer Aufruf auch den identischen Effekt hat - selbst bei einer const-Funktion nicht, weil dazwischen ja nonconst-Methoden von myFooo aufgerufen worden sein könnten, die den inneren Zustand verändern.
Zwar kann man das mit static-Funktionen abbilden, aber IMO ist das nur eine Imitation von freien Funktionen in namespaces....
Sagen wir mal so: Die Existenz von static-Funktionen in Java zeigt mir, dass freie Funktionen eigentlich doch sinnvoll sein können.
Ich hoffe, es wurde etwas klarer, was ich meinte....
Gruß,
Simon2.
-
Simon2 schrieb:
Sagen wir mal so: Die Existenz von static-Funktionen in Java zeigt mir, dass freie Funktionen eigentlich doch sinnvoll sein können.
warum?
mit 'static' funktionen kann man doch das selbe erreichen wie mit freien funktionen, nur passen sie besser zum konzept einer OO sprache wie z.b. Java.
freie funktionen sind nur dann sinnvoll, wenn es keine static-funktionen gibt (und umgekehrt).
ich finde es ist eine gute eigenschaft von Java, dass auf überflüssige und doppelt gemoppelte elemente verzichtet wird. das sorgt u.a. dafür, dass die sprache klar strukturiert und leicht verständlich bleibt...
-
pale dog schrieb:
Simon2 schrieb:
Sagen wir mal so: Die Existenz von static-Funktionen in Java zeigt mir, dass freie Funktionen eigentlich doch sinnvoll sein können.
warum?
...Hups ! Wie habe ich Dich denn in diesen Thread gelockt ?
@Topic: Ganz einfach: static functions sind einfach nicht mehr "OO". Sie beziehen sich nicht mehr auf ein Objekt, sondern führen lediglich mit "extern angelieferten Daten" Operationen aus ... genauso wie freie Funktionen.
Hier bricht Java selbst mit seiner "Alles ist ein Objekt"-Maxime. Das ist auch in Ordnung, denn es ging mir um nicht mehr, als zu zeigen, dass es offensichtlich auch sinnvoll sein kann, aus diese Maxime auszuscheren.(Ich persönlich finde es aus o.g. Gründen konsistenter und eindeutiger, in dem Fall freie Funktionen zu verwenden, aber das spielt hier keine so große Rolle)
Gruß,
Simon2.
-
Saying Java is good because it works on all OSs is like saying anal sex is good because it works on all genders!