const in Java und interface's ...
-
CStoll schrieb:
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.)
Sorry, wenn Eure Auto so geschnitten sind, dass sie eine Änderung der Farbe zulassen, dann seid Ihr selbst schuld. Wenn ich die Möglichkeiten zur Verfügung stelle, dann muss ich mich nicht wundern, wenn sie benutzt werden.
Ausserdem ist es schon komisch, einer 'blauen' Instanz des Objekts 'Farbe' per Accessor in einen anderen Zustand versetzen zu können und sich dann zu ärgern, dass jemand von außen das auch kann.
Warum dann nicht so:
Objekt 'Autolack' mit final Attribut 'Farbe'. getFarbe beim Auto könnte diesen Antworten oder aber nur auf getAutolack reagieren.
Wenn ein Auto jetzt die Farbe ändern will oder das von außen zulassen will, dann muß eine neue Instanz von 'Autolack' mit Attribut bsw. 'rot' erzeugt und gesetzt werden oder nur rot und der Rest passiert intern.
Statt 'Autolack' geht auch einfach ein String-Konstante (weil String per 'call-by-value' benutzt werden).Die Frage ist nur, bietet Auto ein setFarbe an, oder nicht. Wer die aufrufen kann, kann per protected/package/public gelöst werden.
Es stimmt aber, dass ich jetzt nicht die Klasse 'Lackierer' als 'Friend' definieren kann, weil das in Java nicht gibt.
Auch wenn's nicht das selbe ist, dann könnte man ein Interface ILackierer definieren. Wenn Garage dieses nun implementiert und damit 'fähig' ist, denn Lack zu ändern dann ist das auch OK.Man sollte bei der Diskussion auch nicht vergessen, dass ich Kollegen (oder wen auch immer) niemals daran hindern kann, Böses mit dem eigenen Code zu machen. Will sagen:
Wenn mein lieber Kollege R. ein Objekt 'Autobahn' schreibt, das ILackierer implementiert, dann ist der Fehler im System, dass der damit durchkommt und nicht, dass Java nicht die Möglichkeit bietet das zu vermeiden.
Wenn ich in C++ Böses machen will, dann kann ich dort auch auf den Speicherbereichen rumarbeiten.Das Design ist halt einfach etwas anders und (entschuldigt bitte) ich habe manchmal das Gefühl, dass langjährige C-Entwickler (und C++ fällt in diesem Fall unter C) zur Problemlösung zu selten die Möglichkeiten der Objektorientierung nutzen, egal in welcher Sprache (aber kein Vorwurf!).
Vielleicht hilft ein andere Denkansatz ja, wollte niemanden beleidigen und total verwirren - ist halt doch ein Roman geworden.
-
Ja, Schutz gegen Böswilligkeit kann keine Sprache bieten (sie kann entsprechende Versuche nur erschweren), Schutz gegen Fahrlässigkeit dagegen schon.
(und inzwischen habe ich auch eingesehen, daß sich die Sichtweisen von C++ und Java teilweise zu stark unterscheiden - vermutlich ist da ein Grund, warum Anhänger beider Sprachen so oft aneinandergeraten)
OK, werden wir etwas abstrakter: Objektorientierung lebt ja auch von der Interaktion zwischen den Objekten - das läuft dann meistens darauf hinaus, daß ein Objekt an eine Methode des anderen Objekts übergeben wird. Zum Beispiel kann man die Ausgabe lösen als 'printer.print(mein_objekt);' oder als 'mein_objekt.printto(printer);' (aus const-correctness Sicht wäre wohl letzteres angebracht, weil meine Methoden in meiner eigenen Verantwortung liegen). Aber wie sieht es aus, wenn mehr als zwei Objekte an der Interaktion beteiligt sind? (z.B. bekommt ein LGS-Löser eine Matrix M und einen Vektor b und sollte keinen von beiden verändern dürfen)
-
CStoll schrieb:
Ja, Schutz gegen Böswilligkeit kann keine Sprache bieten (sie kann entsprechende Versuche nur erschweren), Schutz gegen Fahrlässigkeit dagegen schon.
Da gebe ich Dir recht, allerdings behaupte ich, dass sich Java da von Haus aus wesentlich besser anbietet... Pointer, Speicherzugriffe, durchgängiges Exceptionhandling, wesentlich einheitlichere API. Wie eigentlich immer, wenn etwas neu ist.
CStoll schrieb:
... lösen als 'printer.print(mein_objekt);' oder als 'mein_objekt.printto(printer);' (aus const-correctness Sicht wäre wohl letzteres angebracht, weil meine Methoden in meiner eigenen Verantwortung liegen)....
Auch hier stimme ich nicht automatisch zu: Für mich ist das eher eine Frage der Fachlichkeit und vor allem der technische Möglichkeiten, ob jedes meiner Objekte selbst weiß, wie es gedruckt wird, oder ob eine 'Drucker' sich damit auskennt und alle anderen Drucken kann.
Gerade bei dem Beispiel ist aber vermutlich sowieso eine Zwischenschicht (XML-Doks o.ä.) sinnvoll, weil zum Druck oft doch alle Daten bekannt sein müssen, die aber im Objektnetz nicht öffentlich sein sollen. Das wäre dann das Mittelding: Jeder legt fest, was gedruckt werden darf/soll/muss und überläßt das wann/wie/womit/... einem andern Objekt (Für den Datenaustausch bietet sich dann übrigens ein Interface und keine konkrete Klasse an).
Oder man benutzt toString :-))Außerdem liegen 'meine Methoden' doch in meiner Verantwortung, die Frage ist doch, wie designe ich meine Methoden und meine Daten. Wenn alles zum Drucken über Getter erreichbar ist, dann kann da doch niemand herummanipulieren.
Davon abgesehen kann ein Drucksystem auch mal ausgetauscht werden oder erweitert, z.B. neben Papierdruck auch Erzeugung von HTML. Dann ist es besser, wenn alle Objekte in einem Format liefern die die eigentliche technische Umstellung/Erweiterung nur im Druck-System stattfindet.
-
SammyRukka schrieb:
Außerdem liegen 'meine Methoden' doch in meiner Verantwortung, die Frage ist doch, wie designe ich meine Methoden und meine Daten. Wenn alles zum Drucken über Getter erreichbar ist, dann kann da doch niemand herummanipulieren.
Siehst du und das ist das Problem - der Drucker darf nur über die Getter zugreifen, aber andere Klassen (z.B. meine Prozesssteuerung) darf auch die Setter-Methoden verwenden. Und da fehlt imho eine Möglichkeit, konsequent zu trennen, wer was machen darf.
Die C++ Umsetzung:
class test { ... public: int get_data() const; void set_data(int); }; class printer { public: virtual void print_test(const test&)=0;//darf nur den Getter nutzen virutal void print_testlist(const vector<test>&)=0;//darf auch nur die Getter der Elemente nutzen }; class manager { public: virtual void update(test&)=0;//hat vollen Zugriff auf alle public-Methoden }; int main() { vector<test> my_data; printer* the_printer = get_system_printer(); ... printer->print_testlist(my_data); }
Und der Versuch in Java:
interface const_test { public int get_data(); }; class test implements const_test { ... public int get_data(){..} public void set_data(int v){..} }; interface printer { public void print_test(const_test);//kann nur die getter nutzen, die const_test deklariert hat public void print_testlist(const_vector<test>);//kann theoretisch alle Methoden von test nutzen }; interface manager { public void update(test); }; class programm { public static void Main(...) { vector<test> my_data = new vector<test>; printer = get_system_printer(); ... printer.print_testlist(my_data);
Das Hauptproblem dabei ist, daß ich entweder meinen kompletten vector kopieren müsste in einen vector<const_test> oder zulasse, daß printer.print_testlist() die Chance hat, meine Objekte zu manipulieren. (und was sich wirklich hinter dem printer verbirgt, liegt nicht mehr in meiner Hand - ich habe nur die öffentliche Schnittstelle)
(das zweite Problem von oben - test.get_data() könnte den Status ändern - ist nicht ganz so kritisch, weil die Methode in meinen Zuständigkeitsbereich fällt)
-
Klar, wie gesagt, 'friend' gibt's nicht, höchsten die Modifier package, protected...
Widersprechen kann ich Dir da auch nicht. Kann nur sagen, daß ich 5 Jahre lange an einer recht großen, vielseitigen und -schichtigen Business-Anwendung entwickelt habe und sich die Probleme in der Praxis nicht gestellt haben. Die Anwendung ist in Subsysteme geteilt mit klaren Schnittstellen (hier Interfaces), an die sich beide Seiten halten mußten. Und da ging man normalerweise auch nicht im fremden Revier wildern.... und sonst könnte man dabei auch die eigentlich geschützte C++-Klasse direkt ändern.... Naja, entweder habe ich einen fachlich Grund etwas zu ändern, dann muß ich es dürfen, oder ich 'kann es eigentlich nicht', habe aber trotzdem die technische Möglichkeit.
public void print_test(const_test);//kann nur die getter nutzen, die const_test deklariert hat
public void print_testlist(const_vector<test>);//kann theoretisch alle Methoden von test nutzenNee, wieso? Das zweite ist falsch (oder ich verstehe Dich falsch)
Das Interface kann ersteinmal gar nichts. Und dann ist es egal, ob Du eine Instanz von const_test übergibst oder mehrere in einem Vector. Entscheidend ist die Schnittstelle von const_test. Und genau hier könntest Du ein Interface 'IConstTestDruckApi' (oder wie auch immer definieren), das wiederum nur die Getter implementiert also sieht das dann so aus:public void print_test(IConstTestDruckApi meinObjekt);
...Ja, auch richtig, das kann ich dann wieder auf die konkrete Klasse casten, aber die Umwege kann man in C++ auch gehen und wenn das jemand deshalb macht...
Für mich:
Was enthält Dein Vector >>const vector<test>&<< in C++ denn, Funktionspointer oder Pointer auf die Attribute?Wie wär's denn sonst mit einem Vector von Paaren Attributname/Value oder einer XML als Austauschformat, da kann auch nichts geändert werden.
Es gibt also auch technisch genügen Möglichkeiten in Java zu Außenschnitttellen ordentlich zu beschreiben. Mit 'Hacker'-Kollegen hat man sowieso Probleme, egal welche Sprache
---
Die Frage ist doch eigentlich auch, wie umfangreich der Druck sein soll. Davon hängt doch auch die Implementierung in C++ ab:
Wenig: Call-by-Value (string in C++ oder String in Java) oder Natives oder wird sie komplexer, dann ist man ganz schnell dabei, daß man sich eine Zwischenschicht ausdenkt.
Wenn ich das 'Information-Hiding' der OO anführe, dann reicht ein const auch nicht, denn lesen kann ich immernoch alles und ist es nicht auch so, daß ich in C die viel gepriesene Möglichkeit habe, über die Adresse eines Attributs doch den Inhalt zu schreiben oder zu verdrehen ?!---
Ach ja, Quasi-Call-by-value erreichst Du ja auch durch ein clone(), dann kann geändert werden was will, die Kopie-Instanz ist ja nicht das Original....
-
CStoll schrieb:
public void print_testlist(const_vector<test>);//kann theoretisch alle Methoden von test nutzen
es muss ja auch
public void print_testlist(const_vector<const_test>);
heissen
-
SammyRukka schrieb:
Klar, wie gesagt, 'friend' gibt's nicht, höchsten die Modifier package, protected...
Widersprechen kann ich Dir da auch nicht. Kann nur sagen, daß ich 5 Jahre lange an einer recht großen, vielseitigen und -schichtigen Business-Anwendung entwickelt habe und sich die Probleme in der Praxis nicht gestellt haben. Die Anwendung ist in Subsysteme geteilt mit klaren Schnittstellen (hier Interfaces), an die sich beide Seiten halten mußten. Und da ging man normalerweise auch nicht im fremden Revier wildern.... und sonst könnte man dabei auch die eigentlich geschützte C++-Klasse direkt ändern.... Naja, entweder habe ich einen fachlich Grund etwas zu ändern, dann muß ich es dürfen, oder ich 'kann es eigentlich nicht', habe aber trotzdem die technische Möglichkeit.
public void print_test(const_test);//kann nur die getter nutzen, die const_test deklariert hat
public void print_testlist(const_vector<test>);//kann theoretisch alle Methoden von test nutzenNee, wieso? Das zweite ist falsch (oder ich verstehe Dich falsch)
Das Interface kann ersteinmal gar nichts. Und dann ist es egal, ob Du eine Instanz von const_test übergibst oder mehrere in einem Vector. Entscheidend ist die Schnittstelle von const_test. Und genau hier könntest Du ein Interface 'IConstTestDruckApi' (oder wie auch immer definieren), das wiederum nur die Getter implementiert also sieht das dann so aus:public void print_test(IConstTestDruckApi meinObjekt);
Wie ich das Interface nenne, ist erstmal egal - const_test in obigem Beispiel enthält alle nötigen Getter, die der Drucker benötigt.
Für mich:
Was enthält Dein Vector >>const vector<test>&<< in C++ denn, Funktionspointer oder Pointer auf die Attribute?Der vector enthält Objekte (vom Typ test) - und ein 'const vector<>&' ist eine Referenz auf so einen vector (mit der Zusicherung, daß er selbst und alle seine Elemente konstant sind).
Wie wär's denn sonst mit einem Vector von Paaren Attributname/Value oder einer XML als Austauschformat, da kann auch nichts geändert werden.
Ja, das läuft wieder darauf hinaus, daß irgendwer alle Objekte des vector<>s kopieren/aufbereiten/... muß, bevor sie an den Drucker übergeben werden können.
Ach ja, Quasi-Call-by-value erreichst Du ja auch durch ein clone(), dann kann geändert werden was will, die Kopie-Instanz ist ja nicht das Original....
Ja, sicher - aber damit kommen wir in die Bereiche, wo die Laufzeit eine Rolle spielt (und der Grund, warum man in C++ const-Referenzen hat - ich habe cbv-Semantik, ohne mich mit den Kosten einer Kopie rumschlagen zu müssen).
Undertaker schrieb:
CStoll schrieb:
public void print_testlist(const_vector<test>);//kann theoretisch alle Methoden von test nutzen
es muss ja auch
public void print_testlist(const_vector<const_test>);
heissen
Und Java erlaubt es wirklich, an DIESE Funktion meinen 'vector<test> my_data' zu übergeben?
-
Undertaker schrieb:
CStoll schrieb:
public void print_testlist(const_vector<test>);//kann theoretisch alle Methoden von test nutzen
es muss ja auch
public void print_testlist(const_vector<const_test>);
heissen
Und Java erlaubt es wirklich, an DIESE Funktion meinen 'vector<test> my_data' zu übergeben?[/quote]
Ja, solange die Klasse test das Interface const_test implementiert hat. Bei dir ist das ja der Fall
PS: Abseits der Diskussion, es ist erstaunlich, wie sehr man sich an die sun coding conventions (insb. Namensgebung/Schreibung) gewöhnt und dann andere Bennenung kaum noch lesen kann.
Klassen und Interfaces: groß,
normalerweise keine Unterstriche sondern mit Großbuchstaben trennen
-
Also eine der ersten Grundlagen in OOP, die ich gelernt habe, ist daß ein Container einer abgeleiteten Klasse kein Container der Basisklasse ist (sonst könnte man ja auch einen vector<Auto> als vector<Fahrzeug> übergeben und bekommt plötzlich Boote dort reingepackt). Und da const kein Java Sprachkonzept ist, dürfte es für den Compiler keinen Unterschied zwischen der Umwandlung vector<Auto> -> vector<Fahrzeug> und vector<test> -> vector<const_test> geben, oder?
PS: @Namen: alles eine Sache der Gewöhnung - in C++ hat sich nunmal komplette Kleinschreibung mit Unterstrichen durchgesetzt
-
Schreibstil:
Geht mir genauso. Auch nach Monaten C++ ist das alles immernoch häßlich für mich. Dazu kommt auch noch die Formatierung an sich. Unter Java/Eclipse hatten wir einen Formatter der beim Speichern darüber ging, so sah das alles sehr ähnlich aus.
Jetzt muß ich mir C++-Code von Generationen von Entwicklern ansehen, die alle so platzraubend und komisch formatieren (und das ist nur die Formatierung)...Du kannst in Java in den Vector jedes 'Object' reinschmeissen. Ob das guter Stil ist, kommt auf die Situation an.
Für mich ist es OK, wenn der Vector 'meineFahrzeuge' heißt und Instanzen von 'PKW', 'Motorrad' und 'Tretroller' enthält, wobei alle am besten von 'Fahrzeug' erben sollten.
Je nach Kontext sind vielleicht sogar 'Boot' und 'Drachenflieger' OK.
In anderen Situationen sollten vielleicht sogar ausschließlich 'PKW' drin sein, durch die Sprache wirst Du da aber nicht festgelegt, außer Du nimmst ein Array von 'KFZ', was ich aber nur selten mache, weil ein Vector viel flexibler ist.
-
SammyRukka schrieb:
Du kannst in Java in den Vector jedes 'Object' reinschmeissen. Ob das guter Stil ist, kommt auf die Situation an.
Für mich ist es OK, wenn der Vector 'meineFahrzeuge' heißt und Instanzen von 'PKW', 'Motorrad' und 'Tretroller' enthält, wobei alle am besten von 'Fahrzeug' erben sollten.Wenn ich auf globaler Ebene einen vector<const_test> hätte, wäre es ja vorstellbar, dort test's reinzuwerfen. Aber umgekehrt in einen vector<test> ein const_test (das eventuell nur gar nicht die set-Methoden definiert hat, die ich im Hauptprogramm benötige) zu packen, ist eine andere Sache.
PS: Wenn der Vector wirklich nur 'Object'e ohne irgendeine Typkontrolle enthält, ist's sogar noch schlimmer - da wird der Nutzer ja gezwungen zu casten, um die Objekte sinnvoll verwenden zu können.
-
Naja, sauber zu arbeiten lohnt sich halt immer.
Auch hier habe ich eigentlich niemals das Problem gehabt, das ich nicht gewußt hätte, was ankommt. Im Gegenteil, manchmal braucht man soetwas ja auch (oder meint das zumindest). Das sind die Fälle, bei denen man in C++ dann Void-Pointer benutzt, da finde ich die Java-Lösung besser.
Das wiederspricht ja auch nicht der OO. Wenn Du da sicher sein willst, dann kannst Du ja auch eine 'KfzListe' implementieren, die die eigentliche Liste und die speziellen Funktionen kapselt.
Ach ja, toString() können sie in Java alle, da brauchst Du keinen Cast!Und zu dem global habe ich so eine andere Meinung. Das ist wie static-Attribute etwas, auf das in 90% der Fälle Höchststrafe stehen sollte.
Außerdem finde ich schon, daß Java typsicher ist. Wenn Du anderer Meinung bist, dann hast Du noch niemals in Smalltalk programmiert - und das ist immerhin die objektorientierte Sprache schlechthin!
---
Aber letztendlich wird das alles sehr offtopic (auch wenn ich ganz interessant finde). Letztlich bleibt zu sagen, daß es für const in Java keinen direkten Pendant gibt, aber halt auch nicht geben muß.
Wenn alles in C++ und Java gleich laufen würde und man nur die Vokabeln getauscht hätte, dann hätte man sich das auch sparen können.
In der Gesamtheit läßt sich aber auch alles lösen, nur halt auf andere Art - genauso paßt dazu das Thema 'multiple Vererbung': Die einen sagen 'braucht Java nicht', die anderen 'kann Java' nicht. Beides ist wahr.
-
SammyRukka schrieb:
Sorry, wenn Eure Auto so geschnitten sind, dass sie eine Änderung der Farbe zulassen, dann seid Ihr selbst schuld. Wenn ich die Möglichkeiten zur Verfügung stelle, dann muss ich mich nicht wundern, wenn sie benutzt werden.
Das ist der Punkt.
mit const garantierst du, dass getFoo nur ein Foo returned ohne das Objekt selber zu ändern. Es ist einfach eine Garantie die das Objekt gibt.
Ausserdem ist es schon komisch, einer 'blauen' Instanz des Objekts 'Farbe' per Accessor in einen anderen Zustand versetzen zu können und sich dann zu ärgern, dass jemand von außen das auch kann.
Warum dann nicht so:
Objekt 'Autolack' mit final Attribut 'Farbe'. getFarbe beim Auto könnte diesen Antworten oder aber nur auf getAutolack reagieren.final bringt dir nichts, ich kann dennoch getFarbe().aendere() aufrufen. Das einzige was funktioniert ist Farbe als immutable zu haben.
Und im Prinzip ist const genau das: du machst aus einem mutable Objekt mit dem qualifier const einfach ein immutable Objekt.
Kleines Beispiel:
Farbe kann immutable sein, aber was wenn man ein Komplexes Objekt hat? zB getMotor().
Wenn Motor nun Operationen hat die den Motor verändern. Beispiel: reparieren().
Wie erlauben wir einem Client einen View auf den Motor ohne dass er rumpfuschen darf? Motor kann nicht immutable sein. In Java würde man jetzt eine defensive Kopie machen. Funktioniert auch problemlos. Meistens hat man ja immutable Objekte und wenn mal nicht, dann halt ne defensive Kopie. Tut nicht wirklich weh. Oder man verlässt sich einfach auf den Client Code - auch sehr legitim.In C++ hat man diese Gedankengänge aber nicht: man liefert einfach einen immutable Motor. Damit kann Auto vom Client Code verlangen: du darfst den Motor ansehen, aber nicht anfassen.
Diese Anforderung kann man natürlich auch in die Doku schreiben und das Programm wird nicht kaputt gehen dadurch. Es ist einfach eine Hilfe um gewissen Fehlern vorzubeugen.
PS:
Wenn dich schon die Formatierungen stören... Dann bist du wohl sehr penibel. Die wirklichen Unterschiede offenbaren sich erst ein paar Levels tieferzB alleine das Klassendesign ist komplett unterschiedlich...
@CStoll:
Java hat keine Templates, ergo wird alles über laufzeit polymorphie gelöst. Generics sind eine automatisierte Variante zum einfügen von den Casts an den richtigen Stellen. Im Prinzip hat man in Java also immer nur vector<Object>
-
SammyRukka schrieb:
Naja, sauber zu arbeiten lohnt sich halt immer.
Auch hier habe ich eigentlich niemals das Problem gehabt, das ich nicht gewußt hätte, was ankommt. Im Gegenteil, manchmal braucht man soetwas ja auch (oder meint das zumindest). Das sind die Fälle, bei denen man in C++ dann Void-Pointer benutzt, da finde ich die Java-Lösung besser.einen void-Zeiger oder ein allgemeines Object zu verwenden nimmt sich im Endeffekt nicht sehr viel - in beiden Fällen mußt du casten, um etwas sinnvolles mit dem Objekt zu machen (ja, Java reagiert da etwas deutlicher, wenn du falsch castest.
Das wiederspricht ja auch nicht der OO. Wenn Du da sicher sein willst, dann kannst Du ja auch eine 'KfzListe' implementieren, die die eigentliche Liste und die speziellen Funktionen kapselt.
Wozu gibt es denn in Java Generics, wenn sie dann doch wieder alles auf 'Object'-Referenzen herunterbrechen? Wenn ich einen vector<KFZ> habe, sollen da nur KFZ's reinkommen und keine Motorboote - indem du erlaubst, diesen als vector<Fahrzeug> oder vector<Object> zu betrachten, unterläufst du die Grundbedingungen (und hast plötzlich doch ein Boot oder gar einen String in dem Vector stehen, der dort nichts zu suchen hat).
Ach ja, toString() können sie in Java alle, da brauchst Du keinen Cast!
Aber toString() ist auch keine eierlegende Wollmilchsau
Und zu dem global habe ich so eine andere Meinung. Das ist wie static-Attribute etwas, auf das in 90% der Fälle Höchststrafe stehen sollte.
OK, vielleicht war 'global' die falsche Bezeichnung - ich meinte damit den vector<> in der Main(), der bei Bedarf herumgereicht werden kann.
Aber letztendlich wird das alles sehr offtopic (auch wenn ich ganz interessant finde). Letztlich bleibt zu sagen, daß es für const in Java keinen direkten Pendant gibt, aber halt auch nicht geben muß.
OK, das sehe ich ein - auch wenn ich die Gründe dahinter immer noch nicht richtig verstehe (bei mir zieht sich const-correctness normalerweise quer durch alle Programmteile).
-
CStoll schrieb:
Wozu gibt es denn in Java Generics, wenn sie dann doch wieder alles auf 'Object'-Referenzen herunterbrechen? Wenn ich einen vector<KFZ> habe, sollen da nur KFZ's reinkommen und keine Motorboote - indem du erlaubst, diesen als vector<Fahrzeug> oder vector<Object> zu betrachten, unterläufst du die Grundbedingungen (und hast plötzlich doch ein Boot oder gar einen String in dem Vector stehen, der dort nichts zu suchen hat).
Es hindert Dich ja auch niemand daran, ein Array zu benutzen oder ein Lsitobjekt (ggf. zu schreiben - nicht kompliziert), dass typsicher ist. Auch hier meine Erfahrung: In den Fällen, in denen ich soetwas brauchte, gab oft auch andere (fachliche) Funktionen, die die Liste gesamt betrafen, so daß sich das sowieso anbot.
Außerdem muß ich zurückrudern *ASCHE AUF MEIN HAUPT*:
[Wo ist der Smilie, der ein rotes Gesicht bekommt?!]
Du hast Recht, Du kannst Listen auch typsicher anlegen, diese Generics (jaja, hast Du ja gesagt) gibt's aber Java 1.5 (glaube ich). Ich habe das noch nie benutzt (ergab sich nie und Java 1.4) und habe das wohl auch recht erfolgreich verdrängt... war zu lange abwesend, weil man mich jetzt ja zu C++ zwingt.
Sorry dafür, das sah vorhin für mich alles falsch aus.CStoll schrieb:
OK, das sehe ich ein - auch wenn ich die Gründe dahinter immer noch nicht richtig verstehe (bei mir zieht sich const-correctness normalerweise quer durch alle Programmteile).
Das ist in Java ja nicht anders, Du gehst halt nur einen anderen Weg. Jetzt ein hinkender Vergleich: Chinesische Schriftzeichen kannst Du auch nicht 1:1 übersetzen, trotzdem kann man übersetzen und die können sich auch unterhalten :-))
Es läuft aber ja darauf hinaus, daß man versucht sauber zu arbeiten, welche Mittel man dazu auch benutzt und nach dem Dialog glaube ich, daß wir beide gegenseitig Code austauschen könnten ohne einen Nervenzusammenbruch zu bekommen.
-
CStoll schrieb:
Wozu gibt es denn in Java Generics, wenn sie dann doch wieder alles auf 'Object'-Referenzen herunterbrechen? Wenn ich einen vector<KFZ> habe, sollen da nur KFZ's reinkommen und keine Motorboote - indem du erlaubst, diesen als vector<Fahrzeug> oder vector<Object> zu betrachten, unterläufst du die Grundbedingungen (und hast plötzlich doch ein Boot oder gar einen String in dem Vector stehen, der dort nichts zu suchen hat).
wenn du eine List<KFZ> hast darfst du da auch nur KFZs reintun und bekommst auch nur KFZs raus. du darfst auch keine List<Motorboot> and eine methode übergeben die eine List<Fahrzeug> erwartet. (gehen würde das allerdings wenn die methode eine List<? extends Fahrzeug> nimmt)
also nur zum klarstellen
-
Ja, er hatte Recht. Ich war nicht voll da.
-
java generics schrieb:
CStoll schrieb:
Wozu gibt es denn in Java Generics, wenn sie dann doch wieder alles auf 'Object'-Referenzen herunterbrechen? Wenn ich einen vector<KFZ> habe, sollen da nur KFZ's reinkommen und keine Motorboote - indem du erlaubst, diesen als vector<Fahrzeug> oder vector<Object> zu betrachten, unterläufst du die Grundbedingungen (und hast plötzlich doch ein Boot oder gar einen String in dem Vector stehen, der dort nichts zu suchen hat).
wenn du eine List<KFZ> hast darfst du da auch nur KFZs reintun und bekommst auch nur KFZs raus. du darfst auch keine List<Motorboot> and eine methode übergeben die eine List<Fahrzeug> erwartet. (gehen würde das allerdings wenn die methode eine List<? extends Fahrzeug> nimmt)
also nur zum klarstellen
Also da lag ich wohl doch richtig.
Kann man eigentlich in Java sowas vernünftig ausdrücken:
interface const_vector<CT> { //getter für Größe und lesenden Elementzugriff }; class vector<T> implements const_vector< "das const-Interface zu T" > { //schreibender Elementzugriff, etc };
-
ich weiß nich genau was du meinst? aber sowas geht:
class vector<T> implements const_vector<T> class vector<T> implements const_vector<? super T>
-
jana generics schrieb:
ich weiß nich genau was du meinst? aber sowas geht:
class vector<T> implements const_vector<T> class vector<T> implements const_vector<? super T>
Das letztere sieht schon so aus, als ob es in die richtige Richtung geht (btw, schließt der Ausdruck <? super T> auch T selber mit ein?). Ich dachte eher an einen Ansatz, daß mein Datenyp irgendwo sagen kann "mein const-interface ist XYZ" (in C++
class text{typedef const_test const_interface;...}
) und daß vector<X> dann das Interface const_vector<x::const_interface> implementieren sollte).(btw, kann man bei Java Methodenüberschreibung auch die Parameter- und Rückgabetypen nachbessern? Sprich: gilt die 'test element(int);' in vector<test> als Definition der 'const_test element(int);' aus dem (von vector<test> implementierten) Interface const_vector<const_test>?