const in Java und interface's ...



  • 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* const

    aber 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 implementierung 👎

    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

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



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

    Nee, 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 nutzen

    Nee, 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?


Anmelden zum Antworten