const in Java und interface's ...
-
Es ist eine Zusicherung für mich, daß jemand anderes meine Objekte nicht ändern wird. Wenn ich einer fremden Funktion ein 'const test&' übergebe, kann diese nur die const-Methoden meiner Klasse verwenden.
Das habe ich auch noch nie verstanden.
Mir, als Benutzer einer Klasse, ist es total egal, ob intern in der Klasse irgendwelche privaten Felder veraendert werden.
Umgekehrt, weis ich, als Programmierer der Klasse, dass wenn der Benutzer eine get Methode aufruft, er keine Interna veraendern kann. Es seih denn ich gestatte es ihm.
Also wozu dann const-Methoden?Den Weg mit "nur get-Interface" ist dazu da einen Immutable und einen Mutable -Typ zu haben. Das hat den Vorteil, dass die immutable Klasse einfacherer uebergeben werden kann, also weniger komplex sein kann.
Siehe dazu String und StringBuilder/StringBuffer.In Java gibts ja auch das Schlüsselwort "final", was im Prinzip das Äquivalent zu const darstellen soll, aber natürlich lange nicht so weitreichend.
Nein, ist es nicht. C++ const und Javas final verhalten sich anders. In C++ ist const auch abhaenig vom Kontex, in Java ist final einfach nur ein Referenz-Konstant.
-
Of course, some consider the STL a bletcherous wart on the backside of C++, and others consider C++ a bletcherous wart on the back side of ComputerScience--so that would make const_iterator a ThirdDegreeWart
ROFL
-
DEvent schrieb:
Of course, some consider the STL a bletcherous wart on the backside of C++, and others consider C++ a bletcherous wart on the back side of ComputerScience--so that would make const_iterator a ThirdDegreeWart
ROFL
ja, c2.com ist nur noch geil
alles sehr lesenswert...
-
Nehmen wir doch mal als Beispiel die Klasse String.
Die kann ich einfach nich veraendern. Egal was ich mache. Es gibt dafuer einfach kein Interface. Wenn ich Strings manipulieren muss, dann muss StringBuilder/StringBuffer her:StringBuilder b = new StringBuilder(meinstring); b.insert b.append b. sonstwas... meinstring = b.toString();
Wo wuerde nun ein C++-Hacker gerne ein const in der String-Klasse sehen?
-
DEvent schrieb:
In C++ ist const auch abhaenig vom Kontex, in Java ist final einfach nur ein Referenz-Konstant.
final ist in java auch sehr stark vom Kontext abhängig.
final class Foo { final void bar(final Baz baz) { final int i=5; } }
-
DEvent schrieb:
Es ist eine Zusicherung für mich, daß jemand anderes meine Objekte nicht ändern wird. Wenn ich einer fremden Funktion ein 'const test&' übergebe, kann diese nur die const-Methoden meiner Klasse verwenden.
Das habe ich auch noch nie verstanden.
Es geht um viel mehr. Auch als Hilfe für einen selber. Wie allen bekannt sein sollte, ist das übergeben von Referenzen wesentlich effizienter als Kopien. Jetzt schreibst du dir eine Funktion die etwas mit diesem Objeket machen soll, zB Ausgeben.
Da du gar nicht vor hast dieses Objekt in der Funktion zu verändern deklarierst du den Parameter natürlich als const-Ref. ( Und jetzt nicht sagen ich pass schon auf das ich nicht falsches in der Funktion mache, bei komplexeren Funktion ist da schnell mal was passiert, zudem ist es doch viel schöner wenn man gar nicht drauf aufpasse muss )
Nun hast du aber das Problem das du zB keine get-Methoden aufrufen könntest die nicht const sind. Deswegen deklarierst du die Funktion als const und stellst für dich selber auch ne Sicherheit auf, dass du this in get() nicht änderst.Es geht aber noch weiter. Häufig stellst du zwei Elementfunktion zur Verfügung, eine const und eine normal. Dadurch hast du auch die Möglichkeit die Funktion im Rückgabewert zu verändern. Nehmen wir mal an du hast ein Matrix Klass oder einfach deinen eigenen Vector:
class MyIntVec { private: int *data; public: int& operator[](size_t i) { return data[i]; } };
Nun arbeitest du ganz normal damit:
MyIntVec vec; // fill vec cout << vec[3]; vec[3] = 23;
Alles noch ok, aber was ist wenn du ein konstantes Objekt haben willst, das irgendwas repräsentieren soll und deswegen fest und unveränderbar sein muss:
const MyIntVec const_vec(othervec.begin(),othervec.begin() + 4); cout << const_vec[3]; // funktioniert nicht
Der Compiler lässt das nicht zu, da er nicht weiß ob op[] nicht doch das Objekt ändern würde.
Ist das nicht toll, das er das für einen prüft.
Nun noch ein :int& operator[](size_t i) const { return data[i]; }
und es funktioniert.
Nun ist op[] const zwar bitweise Konstant aber nicht logisch Konstant.const_vec[3] = 3; // ohh
->
const int& operator[](size_t i) const { return data[i]; }
Schon besser
Das sind zwar einfach Beispiele aber es sollte reichen. Ein const mehr hilft einem sehr zumal man so die Möglichkeit hat auf konstante und nicht konstante Objekte unterschiedlich zu reagieren ...
-
Es geht um viel mehr. Auch als Hilfe für einen selber. Wie allen bekannt sein sollte, ist das übergeben von Referenzen wesentlich effizienter als Kopien. Jetzt schreibst du dir eine Funktion die etwas mit diesem Objeket machen soll, zB Ausgeben.
Da habe ich aufgehoert zu lesen. In Java werden zu 90% Referenzen uebergeben (bis auf die Primitiven). Komischer weise wird das ganz einfach ueber das Interface der Klasse geloest.
final ist in java auch sehr stark vom Kontext abhängig.
Ja, schon klar. Aber es ging eigentlich um Variablen/Parameter. Da ist final eindeutig, anders als das C++ const.
-
DEvent schrieb:
Ja, schon klar. Aber es ging eigentlich um Variablen/Parameter. Da ist final eindeutig, anders als das C++ const.
in gewisser weise nicht
final int == const int
und
final Foo == Foo* constaber ja: das was man in C++ mit const bewerkstelligt gibt es in java nicht.
Mir, als Benutzer einer Klasse, ist es total egal, ob intern in der Klasse irgendwelche privaten Felder veraendert werden.
Genau das ist im Sinne der const-correctness falsch. wenn ich eine lila kuh and die funktion: mache_ein_bild_von_kuh() übergebe, erwarte ich wieder eine lila kuh zu bekommen und keine grüne. const correctness garantiert mir genau das. wenn ich sage: niemand darf meine lila kuh umfärben, sprich:
Kuh lila; Kuh const& konstante_lila_kuh=lila;
dann weiss ich, dass meine lila kuh immer lila bleiben wird.
das ist deshalb vorhanden da man bei primitiven typen ja nichts ändern kann:
int i=3; gib_zahl_aus(i);
i kann sich ja nicht ändern. ich habe die garantie dass i auch nach dem ausgeben 3 ist, weil gib_zahl_aus ja per value nimmt, es kann also i nicht ändern.
bei
Kuh lila=new Kuh(); gib_kuh_aus(lila);
ist diese garantie plötzlich weg.
also haben sich ein paar leute gedacht: eigentlich ist es garnicht so dumm wenn gib_kuh_aus die kuh nicht ändern darf. sprich: wir schützen uns gegen murphy.
dieser schutz ist aber nicht zwingend erforderlich. er erleichtert es sicheren code zu schreiben, aber es ist nicht mehr als ein versprechen. denn um alle verbote kommen wir herum - machiavelli lässt grüßen.
java ist den weg gegangen: es ist nicht 100% erforderlich, also sparen wir uns dieses ganze konzept und halten die sprache simpel.
Da habe ich aufgehoert zu lesen. In Java werden zu 90% Referenzen uebergeben (bis auf die Primitiven). Komischer weise wird das ganz einfach ueber das Interface der Klasse geloest.
und das macht 0 sinn. was wird in java bezüglich const correctness bitte über das interface gelöst?
PS:
in java hat man in manchen situationen eine primitive form der const correctness wenn es mal nötig wird. wenn man einen privaten member von aussen zugänglich machen will, dann braucht man eine kopie oder man bricht die sicherheit der klasse. in c++ hätte man hier einfach ein const T& zurückgegeben und gut ist, da es ein const in java nicht gibt, muss man kopieren.kommt nicht oft vor, aber es kommt vor.
PS2:
genau aus diesem grund gibt es in java vermehrt immutable objekte. diese sind ja quasi konstant. ich kann zB problemlos ein immutable object nach aussen exposen ohne es kopieren zu müssen.
-
Shade Of Mine schrieb:
Mir, als Benutzer einer Klasse, ist es total egal, ob intern in der Klasse irgendwelche privaten Felder veraendert werden.
Genau das ist im Sinne der const-correctness falsch.
genau das ist im sinne der objekt orientierten programmierung aber richtig. ich weiß nichts über den inneren zustand des objekts. const ist wie gesagt nur ein fieser workaround. das kannst du übrigens auch durch dein ganzes beispiel durchziehen. eine methode die eine kuh als parameter bekommt und die dann ausgibt ist anti-oop. die kuh gibt sich selbst aus. in java ist das z.b. mit der toStrign() methode geregelt. das gleiche kannst du so auch für alle anderen möglichen operationen durchziehen. ich schreib auch keine operation gibMilch(Kuh kuh)
http://de.wikipedia.org/wiki/Objektorientierte_Programmierung
-
Ich versuch mich mal an einem anderen Beispiel:
ConstMessage msg = new ConstMessage("Blubba"); MessageDistributer md = getMD(); for(MessageReceiver recv : md.getReceivers()) { recv.notify(msg); }
Stille Post...der letzte Receiver hat leider nicht mehr die Originalnachricht in der Hand.
Edit: Naja, blödes Beispiel, außerdem könnte ConstMessage einfach kein Interface für setNewMessage() anbieten...
...aber bist du dir da auch ganz sicher, dass du nie in die Situation kommst wo ein const sinnvoll wäre?
MfG SideWinder
-
ich bin nich angemeldet schrieb:
genau das ist im sinne der objekt orientierten programmierung aber richtig.
Nein
der zustand eines objektes ist durchaus relevant. es geht dabei um änderungen. ich muss nicht wissen wie es um die kuh steht, ich muss aber sehr wohl wissen ob ihr zustand stabil ist.es gibt dabei 2 zustände: der externe und der intern. was intern abgeht ist mir total egal. aber wenn ich zB ein auto habe und ihm sage:
Farbe f=mercedes.getFarbe();
dann will ich die garantie haben, dass mein schoener neuer mercedes nicht auf 200 km/h beschleunigt.
ob er jetzt bei getFarbe interne werte setzt, wie zB einen farben cache einführt oder aehnliches - ist mir egal.
es geht dabei darum: ich habe ein objekt und zeige es her - danach will ich es in exakt dem zustand haben indem ich es hergegeben habe. denn eine änderung des zustandes des objekts könnte meine klasse kaputt machen.
Beispiel:
Wenn ich eine Garage habe und jemand fragt mich nach der Farbe meines Mercedes:Farbe f = garage.getAutoFarbe("mercedes");
dann erwarte ich, dass der mercedes sich dadurch nicht verfaerbt. denn wenn er das tun wuerde, waere meine garage kaputt da ich nicht mehr:
int num = garage.getAnzahlAnAutosMitFarbe("weiss");
machen kann. denn der cache in garage zählt nicht jedesmal alle farben. wäre ja dumm. er zählt nur beim reinfahren und beim rausfahren der autos. nun wurde der weisse mercedes durch
Farbe f = garage.getAutoFarbe("mercedes"); f.set("rot");
auf rot umgefärbt.
PENG
ich habe mein garagen objekt zerschossen.Java geht nun den weg, dass Farbe einfach immutable ist. das löst das problem natürlich, da ich kein set machen kann. manchmal hat man aber komplexe objekte die nicht immutable sein können, weil ich sie verändern muss. was macht man dann?
-
[quote="Shade Of Mine"]es gibt dabei 2 zustände: der externe und der intern. was intern abgeht ist mir total egal. aber wenn ich zB ein auto habe und ihm sage:
Farbe f=mercedes.getFarbe();
dann will ich die garantie haben, dass mein schoener neuer mercedes nicht auf 200 km/h beschleunigt.{/quote]
nein, das willst du nicht. was die klasse innerhalb ihrere methoden macht ist *ihre* sache. wenn sie es für nötig hält bei einem getFarbe() aufruf zu beschleunigen soll sie das tun. das ist eine sache der konvention und der implementierungBeispiel:
Wenn ich eine Garage habe und jemand fragt mich nach der Farbe meines Mercedes:Farbe f = garage.getAutoFarbe("mercedes");
dann erwarte ich, dass der mercedes sich dadurch nicht verfaerbt. denn wenn er das tun wuerde, waere meine garage kaputt
nein, deine garage wär nicht kaputt. entweder die garage verhält sich so wie sie sich verhält oder du brauchst eine neue garage.
PENG
ich habe mein garagen objekt zerschossen.falsch, das ganze beispiel ist nämlich blödsinn. woher und wieso sollte die garage überhaupt die farben ihrer autos kennen und speichern? wenn dann gäb es eine methode garage.findeAuto("mercedes") und eine methode auto.getFarbe() und/oder auto.setFarbe(Farbe). mal mir mal bitte zu deinem beispiel ein vernünftiges uml klassendiagramm *lol*
irgendwie glaub ich aber das hat keinen sinn hier, ihr (du) denkt einfach zu sehr in euren funktionalen schemata.
gruß
ps: bist du der kleine mti den roten haaren ?
-
SideWinder schrieb:
Ich versuch mich mal an einem anderen Beispiel:
ConstMessage msg = new ConstMessage("Blubba"); MessageDistributer md = getMD(); for(MessageReceiver recv : md.getReceivers()) { recv.notify(msg); }
Stille Post...der letzte Receiver hat leider nicht mehr die Originalnachricht in der Hand.
Edit: Naja, blödes Beispiel, außerdem könnte ConstMessage einfach kein Interface für setNewMessage() anbieten...
ja das beispiel ist schon irgendwie blöd wenn die klasse selber schon ConstMessage heißt wär eine methode setMessage() bissl blöde
...aber bist du dir da auch ganz sicher, dass du nie in die Situation kommst wo ein const sinnvoll wäre?
ja. ich habe ein const noch nie gebraucht weder in java noch in c++ und auch in meinen wenigen c# ausflügen nicht. das hat sich immer durch vernünftiges design vermeiden lassen.
-
besserwißer schrieb:
nein, das willst du nicht. was die klasse innerhalb ihrere methoden macht ist *ihre* sache. wenn sie es für nötig hält bei einem getFarbe() aufruf zu beschleunigen soll sie das tun. das ist eine sache der konvention und der implementierung
ok, also getFarbe() soll das Auto Rot färben, den rückwärtsgang einlegen und dann zum Mond fliegen. Klingt plausibel.
nein, deine garage wär nicht kaputt. entweder die garage verhält sich so wie sie sich verhält oder du brauchst eine neue garage.
eine garage die mir wenn ich sie frage wieviele rote autos drinnen steht eine zufallszahl gibt die nichts mit der anzahl der roten autos in der garage zu tun hat, die ist kaputt.
falsch, das ganze beispiel ist nämlich blödsinn. woher und wieso sollte die garage überhaupt die farben ihrer autos kennen und speichern? wenn dann gäb es eine methode garage.findeAuto("mercedes") und eine methode auto.getFarbe() und/oder auto.setFarbe(Farbe). mal mir mal bitte zu deinem beispiel ein vernünftiges uml klassendiagramm *lol*
erklär mal was daran blödsinn ist. es ist ein simpler cache den ich eingebaut habe.
eine liste cacht infos über die member. Stell dir halt eine Klasse da um Brüche dazustellen:
du hast nen zähler und den nenner. weil du aber die divisionskosten nicht zahlen willst, merkst du dir einfach das ergebnis wenn es einmal berechnet wurde und rechnest nur neu nach wenn sich zähler oder nenner geändert haben.nun macht jemand getZähler() und schon musst du neubrechnen weil er ja uU den zähler damit geändert haben kann.
wenn ich aber getZähler als const habe - dann garantiert mir getZähler() das objekt nicht zu ändern. was zB unheimlich praktisch ist, wenn ich einen wert habe den ich nicht ändern will. zB PI. wäre irgendwie doof wenn jemand PI.setValue(3) machen könnte.
irgendwie glaub ich aber das hat keinen sinn hier, ihr (du) denkt einfach zu sehr in euren funktionalen schemata.
erklärs mir doch
und vorallem warum so ziemlich jeder c++ entwickler mit mir hier falsch liegt. würde mich echt interessieren.const ist einfach eine garantie die man gibt.
-
besserwißer schrieb:
falsch, das ganze beispiel ist nämlich blödsinn. woher und wieso sollte die garage überhaupt die farben ihrer autos kennen und speichern? wenn dann gäb es eine methode garage.findeAuto("mercedes") und eine methode auto.getFarbe() und/oder auto.setFarbe(Farbe). mal mir mal bitte zu deinem beispiel ein vernünftiges uml klassendiagramm *lol*
Und du willst wirklich erlauben, daß die Garage das gefundene Auto nebenbei zum Mond schießen darf?
-
Auf gleiche Weise könnten sich Java Programmierer fragen warum es kein final in C++ gibt (für Klassen und Methoden).
Mit final löst man die Probleme in Java die ein C++ Programmierer mit const löst. final und const sind zwar grundverschieden (abgesehen von primitiven Datentypen) aber Lösen die gleichen Probleme. Allerdings ist die Herangehensweise eine völlig andere.
Das gleiche Thema haben wir z.B. auch bei Interfaces vs. Multiple Vererbung.
In meinen Augen fehlt weder Java ein const noch C++ ein final. Auch sind beide in ihrer jeweiligen Sprache völlig berechtigt und auch nötig. Es ist einfach eine andere Art des Designs. In beiden Welten sind die Benutzer irgendeiner Klasse völlig aufgeschmissen wenn sich der Klassendesigner nicht an die üblichen Konventionen gehalten hat. Weder const, final noch irgend eine andere Spracheigenschaft könnte dann noch wirklich helfen.
MfG,
Hilefoks
-
Hilefoks schrieb:
Mit final löst man die Probleme in Java die ein C++ Programmierer mit const löst. final und const sind zwar grundverschieden (abgesehen von primitiven Datentypen) aber Lösen die gleichen Probleme. Allerdings ist die Herangehensweise eine völlig andere.
Nein. Final und const lösen komplett andere probleme
Aber niemand hier sagt, dass const in java fehlt. Ich habe mehrfach gesagt dass die Probleme die const löst in java anders gehandhabt werden: immutable objekte bzw. defensive kopien.
final wird in c++ anders gemacht: durch das fehlen von virtual hat man etwas das sich ähnlich wie final verhält.
eine klasse ohne virtuellen dtor ist praktisch final. eine nicht virtuelle funktion ist praktisch final.
-
soll das heißen du versuchst in einer anderen klasse (Garage) den internen zustand einens objekts zu verwalten? sorry das ist blödsinn und kein vernünftiges objektorientiertes design. entweder du bringst ein nervünftiges real world beispiel oder ich brauch hier nicht mehr zu lesen
-
asdasd schrieb:
soll das heißen du versuchst in einer anderen klasse (Garage) den internen zustand einens objekts zu verwalten? sorry das ist blödsinn und kein vernünftiges objektorientiertes design. entweder du bringst ein nervünftiges real world beispiel oder ich brauch hier nicht mehr zu lesen
Die Farbe ist doch kein interner Zustand
Aber die Beispiele sind in der Tat nicht geeignet, da const nicht mehr als ein Hilfsmittel für den Programmierer ist. Ein const hat keine Auswirkungen in einem fehlerfreien Programm. Aber um genau das zu erreichen, ein fehlerfreies Programm, bietet es sich an mit const die Möglichkeiten einzuschränken um (ungewollte) Seiteneffekte zu vermeiden. Es ist übrigens möglich innerhalb von einer const-Methode Attribute zu verändern die mit dem Schlüsselwort mutable versehen wurden. Dadurch ist es möglich den internen Zustand eines Objekts zu verändern, aber gleichzeitig kann die Garantie gegeben werden, dass der externe Zustand erhalten bleibt (unter der Annahme, dass bei der Implementierung keine Seiteneffekte auftreten in Verbindung mit den mutable Attributen).
Wenn du sagst man braucht const nicht, dann hast du recht, aber es ist ein Hilfsmittel um Bugs zu vermeiden.
-
asdasd schrieb:
soll das heißen du versuchst in einer anderen klasse (Garage) den internen zustand einens objekts zu verwalten? sorry das ist blödsinn und kein vernünftiges objektorientiertes design. entweder du bringst ein nervünftiges real world beispiel oder ich brauch hier nicht mehr zu lesen
Nein, die Garage verwaltet ihren eigenen Zustand (eine Sammlung von Autos). Mit geeignet gesetzten const's kann ich verhindern, daß sie dabei den internen Zustand dieser Autos beeinflussen kann. (Wenn ich selber die Garage entwickle, weiß ich, was sie tun darf. Aber ein Kollege sieht nur die Methoden der Auto-Klasse und könnte auf die Idee kommen, sie auch zu nutzen.)