Performancemythen?



  • Shade Of Mine schrieb:

    Xin schrieb:

    Ich sehe da nichts abstraktes?! Das alles statisch.

    Abstrakt im Sinne wie Liebe ein abstraktes Nomen ist.
    Denk nicht immer in Java Bahnen. Es geht um OOP nicht um Java.

    Ich sehe da in keinerlei Hinsicht irgendwas abstraktes im Sinne von OOP in Deiner Definition.

    Shade Of Mine schrieb:

    Oder glaubst Du, dass ein Algorithmus dynamisch wird, weil Teile des Programms über ein Template erzeugt wurde?

    Ja. Denn Templates sind in dem Sinne dynamisch als dass sie nicht unänderbar sind. Ich kann sie dynamisch erweitern indem ich neue Objekte hinzufüge ohne den Ursprünglichen Code zu ändern. In einem C++ Interpreter kann ich das zur Laufzeit machen.

    Das ist dynamisch, aber nicht OOP. Neue Templates ändern nicht die Typen vorhandener Daten.

    Shade Of Mine schrieb:

    Templates können zur Laufzeit erstellt werden - siehe C#. Wenn dort ein Generic auftaucht, dann schaut die VM erstmal nach ob eine neue Klasse erstellt werden soll. Und es spricht technisch nichts dagegen C++ Templates genauso zu implementieren. Damit hat man nichts statisches mehr.

    Stimmt, ich kann das Programm zur Laufzeit umschreiben. Das ist dann nicht mehr statisch, aber wenn ich das Programm umschreibe und so nachträglich OOP einfüge oder zur Laufzeit entferne ist das Ändern des Programms nicht OOP, sondern Reflection.
    Selbstmodifizierender Code ist eine sehr alte Geschichte und gab's schon lange, bevor es mit Reflection standardisierte Interfaces dafür gab. Hier wird allerdings mit keinem Objekt gearbeitet, sondern der Code verändert.

    Shade Of Mine schrieb:

    Es geht bei der OOP um das Denken. Wenn ich also das abstrakte Konzept - oder die Idee - von Shape einführe, sind beide Codes gleichwertig: C++ Templates und Java Interfaces.
    Ich kann mit keinem Code mehr machen als mit dem anderen - sie sind vollkommen gleichwertig.

    Ähh... hier muss ich leider widersprechen.. Ein Java Interface entspricht einer Klasse ohne Daten und ausschließlich abstrakten Funktionen.

    class Interface
    {
      public:
        virtual void foo() = 0;
        virtual void bar() = 0;
    };
    

    Templates sind keine Interfaces, Templates sind eine Abstraktionsebene höher, so könntest Du mit z.B. Templates Interfaces erstellen.

    Templates sind keine Interfaces. Templates sind wieder eine ganz andere Baustelle.



  • DEvent schrieb:

    Ich glaub ich versteh langsam wieso um Xins Definition so lange Diskussion gebildet hatt. Die Algemeine Definition von OOP ist
    "Wenn man Daten und Algorithmen zu Klassen abstrahiert und buendelt, von diesen Klassen einzelne Objekte erzeugt und diese Objekte nur noch ueber Nachrichten mit einander kommunizieren, dann ist es OOP."
    Xin stellt diese Definition in Frage, weil man nach dieser Definition alles als OOP bezeichnen kann. Man kann damit also dass

    interface Comparable; class Foo implements Comparable {}
    

    und

    printf(ausgabestream, eingabe)
    

    und

    class Foo { public: void nachricht(x); } foo.nachricht(x);
    

    und vieles andere als OOP bezeichnen.

    Nein. printf hat keinerlei Kopplung zu irgendeinem Objekt. Einfach nur Funktionen in eine Klasse tun reicht nicht aus, damit es objektorientiert ist. Die Zusammenführung muss einen Sinn haben. Zusammenführung von Bitmapdaten mit draw_bitmap(), create_bitmap(), destroy_bitmap(), resize_bitmap() usw. ist sinnvoll.

    EDIT: OK, man könnte aus stdout ein Objekt machen und printf reinfügen....



  • Xin schrieb:

    Wie da steht - ohne virtuell zu sein - kann da nicht objektorientiertes draus werden.

    Das sieht aber ausschließlich du so. Das liegt an _deiner_ verquirlten Definition. So etwas wie virtual kenne ich nur aus C++. Deine OO Ansichten scheinen sich ausschließlich auf C++ zu beziehen. Daher ist mit der Definition wohl nicht viel anzufangen, wenn man nicht gerade C++ programmiert (und selbst da, teilt wohl kaum jemand deine Definition). Nach meiner (und scheinbar zahlreichen gebräuchlichen, wenn mich mir so Artikel/Bücher und andere Programmiersprachen anschaue) Definition(en) ist a.foo() in jedem Fall Objekt Orientiert, da man eine Nachricht an ein Objekt schickt. Wie genau das intern implementiert ist, ist ja vollkommen egal.

    Schau dir doch mal bitte Objective C an. Da ist man eben wesentlich näher an Smalltalk und somit der dynamischen OO. Dort schickt man Signale und der Preprozessor baut daraus eben einen C Aufruf. Ist das deswegen nicht OO, weil die Implementierung einen C Aufruf benutzt?

    rüdiger schrieb:

    Ganz zu schweigen davon, dass du das nicht beurteilen kannst, da du ja nicht weißt was a ist.

    Daher die Relativierung, dass die Aussage gilt, wenn virtual nicht gesetzt ist und zum anderen wurde direkt darunter die Klasse vorgestellt - ohne virtual. Daher kann ich das beurteilen.

    Und einmal mit virtual. Aber wenn du OO von der Deklaration abhängig machst, ist das einfach sehr sehr merkwürdig und ungebräuchlich.

    rüdiger schrieb:

    Was hat printf damit zu tun? Wo siehst du da Nachricht und Objekt?

    Bitte lies das Posting exakt.

    printf ist eine statische Funktion. Sie ist nicht OOP.
    ClassOfA::foo( ClassOfA * ) ist eine statische Funtion. Sie ist nicht OOP.

    Das sind zwei verschiedene Paar Schuhe. Daher lies meine Frage. Statisch/Nicht Statisch hat nichts und rein gar nichts mit OOP zu tun.

    Wenn ClassOfA::foo( ClassOfA * ) OOP, wie behauptet wird, so ist printf ebenfalls OOP in Abhängigkeit des ersten Argumentes.

    Was hat das erste Argument damit zu tun?

    Was der Compiler daraus mag Dir ja egal sein, aber es equivalent zum Sourcecode. Aus einem statischen Funktionsruf wird ohne Compilerfehler kein OOP mehr.

    Aber sicher. Weil der Aufruf im Hintergrund ist egal. Was soll dort den Unterschied machen? Dann sind ja selbst virtuelle Funktionen nicht garantiert OO nach deiner (merkwürdigen!) Definition.

    class A {
    public:
      virtual void foo() { }
    };
    
    class B {
    public:
      virtual void foo() { }
    };
    
    B b;
    b.foo();
    

    daraus wird ja auch ein "statischer Aufruf", zumindest erwarte ich das bei einem guten Compiler. => Kein OO

    rüdiger schrieb:

    Xin schrieb:

    Ich sehe da nichts abstraktes?! Das alles statisch.
    Oder glaubst Du, dass ein Algorithmus dynamisch wird, weil Teile des Programms über ein Template erzeugt wurde?

    Abstrakt und Statisch sind keine Gegensätze und was genau meinst du mit dynamisch?

    Wahl einer statischen Funktion aufgrund eines Algorithmus.
    Es gibt keine dynamischen Funktionen (ohne Reflection), es gibt virtuelle Funktionen, die aufgrund der OO-Technik eine statische Funktion aufrufen.

    Ich verstehe nicht was du mir sagen willst.

    rüdiger schrieb:

    Es gibt zahlreiche andere Definitionen hier in dem Thread, die ebenfalls "scharf" sind.

    Das wird in dem Thread nicht nur von mir bestritten.

    das es zahlreiche Definitionen hier gibt? Das willst du bestreiten? Das diese "scharf" sind? Schau dir zB die Definition von Overtaker an. Die ist gut. Vielleicht nicht ganz 100% ausgearbeitet. Trifft aber zumindest schon den Nagel.

    rüdiger schrieb:

    Deine ist einfach nur Falsch in der Hinsicht, dass die Mehrheit der Programmierer sie wohl einfach nicht teilt.

    Die Hinsicht, das die Mehrheit der Programmierer sie teilt, wäre somit richtig.
    Diese Mehrheit findet sich offenbar nicht in diesem Forum.

    Wo findest du bitte die Mehrheit? Nach deinen Regeln kann ja höchstens C++ OO sein und damit stößt du glaube ich schon mal vielen Leuten vor den Kopf...



  • Jester schrieb:

    Xin, ich denke schon, dass wir Deine Definition inzwischen verstanden haben. Wir halten sie nur nach wie vor für falsch. Es bringt also nichts diese stoisch immer wieder zu wiederholen.

    Wenn ClassA::foo tatsächlich so wenig mit dem Objekt zu tun hat wie printf mit dem formatstring, dann hast Du recht. Es handelt sich dann um einen schlichten Designfehler, foo sollte dann nicht ClassA zugehörig sein.

    Das zeigt leider, dass Du mich nicht verstehst.
    "foo" kann ClassOfA zugehörig sein, die statische Funktion heißt dann "ClassOfA::foo", genauso wie "printf" "std::printf" heißt.
    Die Tatsache, dass "ClassOfA" eine Class ist, gibt an, dass das erste Argument von ClassOfA::foo immer vom Typ ClassOfA * ist, sofern foo nicht als static deklariert ist. Ein Namespace ist equivalent zu einer Klasse, die ausschließlich static Member besitzt.
    Der Unterschied ist das erste Argument, das als "Syntax-Zucker" (wort habe ich in diesem Thread gelernt ;-)) implizit unter dem Namen "this" übergeben wird.

    Jester schrieb:

    Man könnte sagen (auch wenn ich das inzwischen für etwas ausgelutscht halte), das Programm orientiert sich am Objekt, nämlich dessen aktuellem Zustand. Und es wird ja keiner behaupten wollen, dass der Zustand eines Objektes in Wirklichkeit der Klasse zugehörig ist, oder?

    Stimmt, ein Objekt kann aber genauso gut ein Integer sein und ein Assemblerprogramm kümmert sich auch um Integer-Objekte, also wäre jedes Assemblerprogramm objektorientiert, zieht man die Konsequenz aus Deiner Aussage.
    Die CPU wäre ebenfalls ein Objekt, da sie den Zustand des laufenden Programms bezeichnet und der Status des Programms durch den Sceduler in eigenen Objekten im RAM abgelegt wird.

    Jester schrieb:

    Du wirst dieser Definition zumindest den gleichen Grad an Präzision und Gültigkeit zugestehen müssen wie Deiner eigenen. Es steht schließlich nirgends geschrieben, dass "orientieren" heißt "orientiert sich am Typ". Das ist lediglich Deine persönliche Interpretation davon, die die meisten anderen offensichtlich nicht teilen.

    Stimmt, wenn Du so interpretierst, wie Du grade aufgeführt hast, dann zieh auch die Konsequenzen aus Deiner Aussage und bestätige, dass jedes Assemblerprogramm objektorientiert ist. Und natürlich auch alle C Programme, die Daten in beliebiger Art (eben Objekte) verarbeiten. Eben alles, was irgendwie mit Objekten arbeitet, ist objektorientiert und wir haben durch die Multimethoden und PHP und Co. schon festgestellt, dass wir nicht auf Klassen angewiesen sind.

    Konsequent angewendet, verpufft "diese" Definition. Zumal "diese" Defenition und das "wir" von dem Du sprichst, sich großenteils (eben nicht alle) einig ist, dass man gegen mich ist, ihr euch mit euren Argumenten aber genauso widersprecht, wie mir. Es gibt keine "diese" Definition, es gibt nur viele Postings, die mit "Ich finde..." beginnen.

    Meine Definition kommt da zu anderen Ergebnissen. Freie Wahl der Objekte und trotzdem klare Ansage, was OOP ist und was nicht.



  • In einer vollkommenen OO Programmiersprache bieten nur Objekte Funktionen, globale Funktionen die keinem Objekt zugeordnet sind gibt es nicht, denn es existieren nur Objekte.

    Das wäre der Unterschied zwischen
    a -> plus (Integer b)
    und
    plus(Integer a, Integer b)
    Das erste ist ein Objekt, dass zweite eine Funktion.

    Compilerdetails einer Sprache wie C++ interessieren einen herzlich wenig, das Design, der Sourcecode, die Sprache ist das entscheidende, nicht der Computer.

    ... um auf die Frage von Seite 11 ... ähm 12 zu antworten.



  • rüdiger schrieb:

    Xin schrieb:

    Wie da steht - ohne virtuell zu sein - kann da nicht objektorientiertes draus werden.

    Das sieht aber ausschließlich du so. Das liegt an _deiner_ verquirlten Definition. So etwas wie virtual kenne ich nur aus C++. Deine OO Ansichten scheinen sich ausschließlich auf C++ zu beziehen.

    APPLAUS APPLAUS APPLAUS!
    scnr 😉

    Natürlich kennst Du virtual nur aus C++, weil in anderen OO-unterstützenden Sprachen, wie zum Beispiel Java virtual die default-Strategie ist. Man schreibt nicht virtual, also findest Du es dort auch nicht.
    Durch eine andere Syntax, ändert sich die Definition von OOP aber nicht.

    rüdiger schrieb:

    Daher ist mit der Definition wohl nicht viel anzufangen, wenn man nicht gerade C++ programmiert (und selbst da, teilt wohl kaum jemand deine Definition).

    Es geht nicht um das Schlüsselwort virtual, sondern um das, was C++ macht, wenn man virtual benutzt.
    Das ist das gleiche, wenn man in Java überhaupt nichts schreibt.
    Schreibt man in Java

    class ClassOfA 
    {
      void foo();
      abstract void bar();
    }
    

    entspricht das in C++

    class ClassOfA
    {
      virtual void foo();
      virtual void bar() = 0;
    };
    

    Entsprechend zu Objective C auf C: Man braucht nicht virtual für OOP, man braucht virtual, wenn man OO-unterstützung von C++ wünscht, weil C++ sonst auf OOP verzichtet.
    Andere Sprache, andere Syntax - aber OOP ist eine Technik zur dynamischen Auflösung von Funktionsaufrufen und die Technik ändert sich in anderen Sprachen nicht, genausowenig wie verkettete Listen in unterschiedlichen Sprachen immernoch verkette Listen bleiben, aber mit einer anderen Syntax programmiert werden.

    rüdiger schrieb:

    rüdiger schrieb:

    Ganz zu schweigen davon, dass du das nicht beurteilen kannst, da du ja nicht weißt was a ist.

    Daher die Relativierung, dass die Aussage gilt, wenn virtual nicht gesetzt ist und zum anderen wurde direkt darunter die Klasse vorgestellt - ohne virtual. Daher kann ich das beurteilen.

    Und einmal mit virtual. Aber wenn du OO von der Deklaration abhängig machst, ist das einfach sehr sehr merkwürdig und ungebräuchlich.

    Merkwürdig, weil ungewohnt. Aber zum merken würdig.
    Ungebräuchlich - stimmt, merkt man an diesem Thread.

    Aber logisch.

    rüdiger schrieb:

    Das sind zwei verschiedene Paar Schuhe. Daher lies meine Frage. Statisch/Nicht Statisch hat nichts und rein gar nichts mit OOP zu tun.

    Ein direkter Aufruf einer statischen Funktion ist nicht objekt orientiert. Objektorientiert ist, abhängig vom Objekttyp die richtige statische Funktion auszuwählen und aufzurufen.

    rüdiger schrieb:

    Wenn ClassOfA::foo( ClassOfA * ) OOP, wie behauptet wird, so ist printf ebenfalls OOP in Abhängigkeit des ersten Argumentes.

    Was hat das erste Argument damit zu tun?

    Bei statischen, objektzugehörigen Funktionen (das meint also nicht "static"), ist das erste Argument der this-Pointer.

    rüdiger schrieb:

    Was der Compiler daraus mag Dir ja egal sein, aber es equivalent zum Sourcecode. Aus einem statischen Funktionsruf wird ohne Compilerfehler kein OOP mehr.

    Aber sicher. Weil der Aufruf im Hintergrund ist egal. Was soll dort den Unterschied machen? Dann sind ja selbst virtuelle Funktionen nicht garantiert OO nach deiner (merkwürdigen!) Definition.

    class A {
    public:
      virtual void foo() { }
    };
    
    class B {
    public:
      virtual void foo() { }
    };
    
    B b;
    b.foo();
    

    daraus wird ja auch ein "statischer Aufruf", zumindest erwarte ich das bei einem guten Compiler. => Kein OO

    Richtig, wie auf den letzten 5-10 Seiten immer wieder beschrieben. Es hat jemand etwas verstanden. 🙂
    Wenngleich eine Optimierung des Compilers zum Entfernen von OOP das uninteressanteste an OOP ist.
    Ein guter Compiler entfernt hier den überflüssigen OOP-Aufruf und schreibt hier einen schnelleren, statischen Funktionsruf ins Executable.

    rüdiger schrieb:

    Xin schrieb:

    Ich sehe da nichts abstraktes?! Das alles statisch.
    Oder glaubst Du, dass ein Algorithmus dynamisch wird, weil Teile des Programms über ein Template erzeugt wurde?

    rüdiger schrieb:

    Abstrakt und Statisch sind keine Gegensätze und was genau meinst du mit dynamisch?

    Wahl einer statischen Funktion aufgrund eines Algorithmus.
    Es gibt keine dynamischen Funktionen (ohne Reflection), es gibt virtuelle Funktionen, die aufgrund der OO-Technik eine statische Funktion aufrufen.

    Ich verstehe nicht was du mir sagen willst.

    Das merke ich, das tut der Rest offenbar auch nicht, aber ich finde es sehr gut, dass Du daraus hier nicht wie der Rest schlussfolgerst, dass mein Ansatz falsch ist. 👍

    Wie kann ich Dir beim Verständnis helfen?

    Ich versuche es mal damit: abstract und static sind Gegensätze.
    Eine abstrakte Funktion arbeitet objektorientiert, eine statische nicht.
    In C++ sähe das statisch abstrakt so aus:

    void ClassOfA
    {
      static virtual void foo();
    };
    

    was aussagt, dass die Funktion ohne Objekt objektorientiert zu rufen ist.
    Und der Compiler wird dazu etwas sagen, was mit "error" beginnt.

    rüdiger schrieb:

    rüdiger schrieb:

    Es gibt zahlreiche andere Definitionen hier in dem Thread, die ebenfalls "scharf" sind.

    Das wird in dem Thread nicht nur von mir bestritten.

    das es zahlreiche Definitionen hier gibt? Das willst du bestreiten? Das diese "scharf" sind? Schau dir zB die Definition von Overtaker an. Die ist gut. Vielleicht nicht ganz 100% ausgearbeitet. Trifft aber zumindest schon den Nagel.

    Ich habe noch keine saubere Definition hier gelesen. Ich habe viele gelesen, offenbar ist die von Overtaker mir nicht unter den anderen aufgefallen. Ich bestreite hier eine scharfe Definition gesehen zu haben. Viele Definitionen habe ich gelesen und alle behaupten, dass es *die* eine ist, die alle anderen auch haben.
    Kann sein, dass Overtaker da untergegangen ist.
    Lohnt es sich, sie zu suchen? Kann sie meine Frage an Hustbaer beantworten - sonst lohnt es sich icht.



  • Tellerrand schrieb:

    In einer vollkommenen OO Programmiersprache bieten nur Objekte Funktionen, globale Funktionen die keinem Objekt zugeordnet sind gibt es nicht, denn es existieren nur Objekte.

    Das wäre der Unterschied zwischen
    a -> plus (Integer b)
    und
    plus(Integer a, Integer b)
    Das erste ist ein Objekt, dass zweite eine Funktion.

    Compilerdetails einer Sprache wie C++ interessieren einen herzlich wenig, das Design, der Sourcecode, die Sprache ist das entscheidende, nicht der Computer.

    ... um auf die Frage von Seite 11 ... ähm 12 zu antworten.

    Du beantwortest die Frage damit, dass Du die Frage wiederholst und statt ein Fragezeichen einen Punkt setzt.
    Die Frage war nach dem "Warum".

    Zu behaupten, dass Methoden Funktionen sind, die ein implizites Argument (this) haben, nicht interessiert, ändert die Programmierweise nicht.
    Sich die Augen zuzuhalten ist keine sinnvolle Antwort.

    Es gibt keinen unterschied zwischen
    Integer Integer::plus( Integer * this, Integer b )
    und
    Integer plus( Integer a, Integer b ).

    Die eine Funktion heißt "Integer::Plus", die andere "plus" und beide sind statisch.



  • Xin schrieb:

    Die Frage, die ich hustbaer stellte - sorry, war Seite 12:

    xin schrieb:

    hustbaer schrieb:

    Wenn man diese Definition von OO(P) verwendet heisst das noch lange nicht dass man hier irgendwelche abstrakten Klassen, Polymorphie oder virtuelle Aufrufe braucht. Wenn ein Programm so entworfen ist dass "die Auswahl des auszuführenden Codes" immer zur Compile-Zeit erfolgen kann (ohne natürlich den "falschen" Code auszuwählen), dann ist das kein Grund warum das Programm nichtmehr "OO" wäre.

    Und welche Begründung gibt es, es "OO" zu nennen?
    Nachrichten gibt's in rein prozeduralen Sprachen, in C++ wird es in Funktionsaufrufen gehandhabt.
    Man könnte auch überall, was da in Wirklichkeit ja auch steht, die Funktion korrekt ausschreiben:

    tier.Tier::Funktion( typ Parameter )
    

    Das unterscheidet sich von

    tier_Funktion( Tier * tier, typ Parameter )
    

    nicht. Die Methode heißt Tier::Funktion( Tier *, typ ). Wo ist der Unterschied zu "tier_Funktion( Tier *, typ )?
    Es passiert dasselbe und es wird auch dasselbe übersetzt. Es ist in der Implementierung identisch. Es ist semantisch identisch, beides kann als Nachricht übermittelt werden und beides wird in C++ als Funktionsaufruf umgesetzt.
    Warum ist das eine für Dich "OO" und das andere nicht? Wo beschreibt die Masse einen Unterschied, der den Namen "objekt orientiert" rechtfertigt?

    ...und beides wird in C++ als - statischer - Funktionsaufruf umgesetzt.

    Sorry, ich habe mich hier etwas zurücckgenommen, u.A. auch deswegen weil du die Angewohnheit hast entweder Antworten nicht ganz zu lesen, einem das Wort im Mund zu verdrehen und/oder deine Diskussionspartner für Vollvasen zu halten. Welches der drei zutrifft kann ich nicht sagen, ist aber auch egal.

    Was mein Standpunkt ist: *WENN* der statisch Funktionsaufruf die *RICHTIGE* Funktion aufruft, dann ist das OO. (Dass du mir dann auf meine Frage hin mit einem Beispiel ankommst wo mit einem statischen Aufruf die falsche Funktion aufgerufen wird ist ein Beispiel für das was ich im Absatz oben meinte: nicht sachdienlich, und ignoriert/verdreht komplett was ich geschrieben habe.)

    Wenn der statische Funktionsaufruf die falsche Funktion aufruft ist es ein falsches Programm, welches aber immernoch OO ist. Wenn er die falsche Funktion aufruft die aber an der Stelle trotzdem "das Richtige" macht ist es ebenso ein OO Programm, und nicht wirklich "falsch", aber IMO sehr unsauber.

    ----

    IMHO geht es bei Objektorientierung viel mehr darum wo Daten gehalten werden (und von miraus noch welche Funktionen darauf zugreifen können/dürfen/sollen).
    Objektorientierung heisst für mich auch weiters "Daten nur in Objekten" - also keine globalen Daten, keine "stateful" Funktionen. Daten zu Objekten zusammen fassen, also Orientierung an Objekten, nicht an einzelnen Werten. Anders gesagt: "Objektorientierung". Kurz: "OO".

    Andere Dinge wie das "dynamic dispatch" auf dem du die ganze Zeit herumreitest (sorry) sind IMO zwar wirklich toll (nicht ironisch gemeint!), aber eben nicht Teil von OO. Anders gesagt: dynamic dispatch und OO sind orthogonale Prinzipien. Genauso wie Vererbung, Abstrakte Typen/Interfaces, Reflection etc.

    Wenn das für viele jetzt sehr "basic" klingt... denkt mal darüber nach wann der Begriff OO(P) geprägt wurde, und wie damals "typische" Programme (real life, nicht akademisch, production code) ausgesehen haben. Soll heissen: damals wurde grösstenteils NICHT OOP (unter meiner "Definition") programmiert, und daher machte es auch Sinn diesem "anderen Programmierstil" einen Namen zu geben.

    ----

    OO und "dynamic dispatch" sind wie Laufen und Fit sein. OO ohne "dynamic dispatch" ist immernoch OO, genauso wie Laufen ohne Fit sein trotzdem Laufen ist. Beides ist aber mit dem jeweils anderen ungemein leichter und "mächtiger". (Genauso könnte man sagen führt das eine über kurz oder lang zum anderen - oder zumindest zu dem Wunsch nach den anderen. Trotzdem wird es nicht zu einer Voraussetzung. Oft macht es immer noch Sinn dass jmd. läuft der nicht Fit ist, genauso wie es oft Sinn macht dass man OO ohne "dynamic dispatch" macht.)



  • Xin schrieb:

    rüdiger schrieb:

    Und einmal mit virtual. Aber wenn du OO von der Deklaration abhängig machst, ist das einfach sehr sehr merkwürdig und ungebräuchlich.

    Merkwürdig, weil ungewohnt. Aber zum merken würdig.
    Ungebräuchlich - stimmt, merkt man an diesem Thread.

    Aber logisch.

    Nein, überhaupt nicht logisch.

    Xin schrieb:

    rüdiger schrieb:

    Das sind zwei verschiedene Paar Schuhe. Daher lies meine Frage. Statisch/Nicht Statisch hat nichts und rein gar nichts mit OOP zu tun.

    Ein direkter Aufruf einer statischen Funktion ist nicht objekt orientiert. Objektorientiert ist, abhängig vom Objekttyp die richtige statische Funktion auszuwählen und aufzurufen.

    Der Aufruf ist doch Abhängig vom Objekt. Bei einem Objekt der Klasse A mit dem Methoden Aufruf foo, wird anhand der Klasse des Objektes der Aufruf entschieden. Egal ob das nun zur Laufzeit statt findet oder zur Compilezeit. Ich versteh nicht, warum du das zwanghaft auf die Laufzeit schieben willst. Macht doch überhaupt gar keinen Sinn dort eine künstliche Barierre einzuführen, die die Mehrheit einfach nicht sieht.

    Xin schrieb:

    rüdiger schrieb:

    Wenn ClassOfA::foo( ClassOfA * ) OOP, wie behauptet wird, so ist printf ebenfalls OOP in Abhängigkeit des ersten Argumentes.

    Was hat das erste Argument damit zu tun?

    Bei statischen, objektzugehörigen Funktionen (das meint also nicht "static"), ist das erste Argument der this-Pointer.

    Jo, bei Methoden hat man irgend wo den this-Pointer noch drin. Egal ob die zur Lauf- oder Compilezeit dispatcht werden.

    Xin schrieb:

    rüdiger schrieb:

    Was der Compiler daraus mag Dir ja egal sein, aber es equivalent zum Sourcecode. Aus einem statischen Funktionsruf wird ohne Compilerfehler kein OOP mehr.

    Aber sicher. Weil der Aufruf im Hintergrund ist egal. Was soll dort den Unterschied machen? Dann sind ja selbst virtuelle Funktionen nicht garantiert OO nach deiner (merkwürdigen!) Definition.

    class A {
    public:
      virtual void foo() { }
    };
    
    class B {
    public:
      virtual void foo() { }
    };
    
    B b;
    b.foo();
    

    daraus wird ja auch ein "statischer Aufruf", zumindest erwarte ich das bei einem guten Compiler. => Kein OO

    Richtig, wie auf den letzten 5-10 Seiten immer wieder beschrieben. Es hat jemand etwas verstanden. 🙂
    Wenngleich eine Optimierung des Compilers zum Entfernen von OOP das uninteressanteste an OOP ist.
    Ein guter Compiler entfernt hier den überflüssigen OOP-Aufruf und schreibt hier einen schnelleren, statischen Funktionsruf ins Executable.

    Benutz bitte nicht das Wort OOP so, auch wenn deine verquirlte Definition davon das Wort zu einem Ersatz von "virtuellen Funktionsaufruf" gemacht hat. Das verwirrt einfach nur.

    Aber zum Thema: Also ist es nicht OOP. Aber eigentlich ist OOP doch eine Methode zu programmieren und Programme zu entwerfen. Nicht etwas, was der Compiler entscheidet.

    Das merke ich, das tut der Rest offenbar auch nicht, aber ich finde es sehr gut, dass Du daraus hier nicht wie der Rest schlussfolgerst, dass mein Ansatz falsch ist. 👍

    Es gibt kein "Falsch" bei Definitionen. Das habe ich ja auch schon erklärt. Ich definiere etwas, also lege ich es damit fest. Ist nur die Frage, ob ich mich dann immer noch mit anderen Menschen verständigen kann, weil diese vielleicht eine andere Definition haben. Wie ich mehrfach sagte: Du kannst auch Grün zu Blau sagen.

    Xin schrieb:

    rüdiger schrieb:

    rüdiger schrieb:

    Es gibt zahlreiche andere Definitionen hier in dem Thread, die ebenfalls "scharf" sind.

    Das wird in dem Thread nicht nur von mir bestritten.

    das es zahlreiche Definitionen hier gibt? Das willst du bestreiten? Das diese "scharf" sind? Schau dir zB die Definition von Overtaker an. Die ist gut. Vielleicht nicht ganz 100% ausgearbeitet. Trifft aber zumindest schon den Nagel.

    Ich habe noch keine saubere Definition hier gelesen. Ich habe viele gelesen, offenbar ist die von Overtaker mir nicht unter den anderen aufgefallen. Ich bestreite hier eine scharfe Definition gesehen zu haben. Viele Definitionen habe ich gelesen und alle behaupten, dass es *die* eine ist, die alle anderen auch haben.
    Kann sein, dass Overtaker da untergegangen ist.
    Lohnt es sich, sie zu suchen? Kann sie meine Frage an Hustbaer beantworten - sonst lohnt es sich icht.

    Welche Frage an Hustbaer? Es lohnt sich die Definition zu suchen, da es die einzige Definition ist, die ich bisher gefunden habe, die wirklich alle Objektsysteme (die ich kenne) einschließt.

    Das ist vielleicht auch der Unterschied zwischen deiner Definition und meiner Definition. Du setzt dich hin und sagst "vom Himmel hinaus": X ist OOP. Alles andere nicht. Ich schaue mir an, was ich über OOP finde und lese und was andere Leute sich darunter vorstellen (oder war ich vermute, was sie sich vorgestellst haben) und versuche dann eine Definition zu treffen, die dem Gerecht wird.

    Ich fürchte einfach, dass du nicht viele OO-Systeme kennst. Da dein statisch/nicht-statisch-Ansatz nur mit C++ funktioniert. In anderen Sprachen wird jeder Funktionsaufruf zur Laufzeit dispatcht. Sind das dann komplett Objektorientierte Sprachen? Ich fürchte nicht...



  • *amateurmoderator : start*

    Die Definition von overtaker ist auf Seite 30.

    *amateurmoderator : ende*



  • Xin schrieb:

    Shade Of Mine schrieb:

    Xin schrieb:

    Wo ist da ein abstraktes Konzept, dass nicht im Sourcecode vorkommt?

    Ich pack den Code hier nochmal rein, damit wir überhaupt sicher sind, dass wir vom gleichen sprechen:

    Shade Of Mine schrieb:

    Mir ist gerade langweilig, deshalb ein kleines Gedankenspielchen:

    class Triangle {
    public:
      void draw();
    };
    
    class Circle {
    public:
      void draw();
    };
    
    template<typename Shape>
    void foo(Shape* s) {
      s->draw();
    }
    

    Das Konzept hier ist Shape. Genau wie in Java oder sonstwo wo man eine abstrakte Klasse/Interface hätte. Lediglich manifestiert es sich nicht direkt im Code in form einer Klasse/Interface sondern viel mehr im Sinne eines abstrakten Konzepts.

    Ich sehe da nichts abstraktes?! Das alles statisch.
    Oder glaubst Du, dass ein Algorithmus dynamisch wird, weil Teile des Programms über ein Template erzeugt wurde?

    Mir ist jetzt nicht klar was Abstraktion mit Dynamik zu tun hat aber eines ist mir klar: Abstraktion passiert im Kopf, nicht im Code.



  • interessantes Statement (Quelle: http://www.cincomsmalltalk.com/userblogs/ralph/blogView?showComments=true&entry=3364027251 )

    Ralph Johnson schrieb:

    Processes in Erlang are objects. At the beginning of my course on OO design, I explain three views of OO programming. The Scandinavian view is that an OO system is one whose creators realize that programming is modeling. The mystical view is that an OO system is one that is built out of objects that communicate by sending messages to each other, and computation is the messages flying from object to object. The software engineering view is that an OO system is one that supports data abstraction, polymorphism by late-binding of function calls, and inheritance.

    (und generell interessant, vor allem für Leute die Erlang noch nicht kennen. Was eigentlich viel interessanter ist, als die OOP Definition von irgend wem...)



  • Habe mal im IRC diskutieren mit dv und dabei ist folgende definition herausgekommen:

    OO eine Denkweise wie man Daten und Methoden gruppieren kann, dabei zeichnet sich die Gruppierung durch die Einteilung in Objekten=Daten+Methoden aus. OOP ist die implementierung von der OO denkweise, die die encapsulation, inheritance, and polymorphism Techniken benutzt.

    Was haltet ihr davon?



  • Dem ersten Satz stimme ich zu, dem zweitem nicht ganz. OOP ist auch ohne Vererbung und Polymorphie moeglich.



  • Dem ersten Satz stimme ich auch nicht wirklich zu. Siehe CLOS.



  • Vorweg, wenn ich im Folgenden von Weltbild spreche, dann beziehe ich das auf die Welt der Programmierung. (Ist eh die einzige Welt in der ich lebe)

    Über die Jahre habe ich mir angewöhnt, Aussagen, die ich nicht begreife um so gründlicher zu lesen. Weil immer dann, wenn jemand etwas sagt was nicht in "mein" Weltbild passt könnte es dafür zwei Gründe geben: Mein Weltbild ist unzureichend oder aber die Aussage ist fehlerhaft.

    Nach immerhin einem viertel Jahrhundert seid ich meine ersten Programme in Computer gehackt habe bilde ich mir nunmal ein das mein Weltbild, wenn auch streckenweise unkonventionell, insgesamt doch recht fundiert ist. (Mal abgesehen davon das ich menschlich halt ein bekanntes Arschloch hier im board bin, aber das ist ein andere Thema)

    Meine Theorie ist, daß alles was ich nicht verstehe eine Chance sein kann, mein Wissen weiter zu fundieren indem ich versuche es zu verstehen, anstatt alles was nicht in "mein" Weltbild passt grundsätzlich als falsch abzulehnen, wodurch ich mir selber letzten Endes die Chance nehmen würde mich weiterzuentwickeln. Dabei kann selbst eine totale Falschaussage mir helfen mein Wissen weiter zu fundieren, denn wie heisst es so schön: Der kluge lernt aus seinen Fehlern, der Weise aus den Fehlern der Anderen.

    Betrachte ich nun Xin's missionarischen Eifer mit dem er sein Weltbild unter die Leute bringt kombiniert mit dem fast schon krankhaft anmutenden Zwang alles andere als Falsch entlarven zu müssen dann werde ich stutzig. Sicher, zum Teil klingen seine Aussagen gar nicht so falsch, streckenweise vor allem am Anfang hatte ich sogar das Gefühl ihm zustimmen zu wollen, aber jeh mehr ich verstehe was er sagen will, desto weniger kann ich dem zustimmen.

    Zwischen den Zeilen lese ich immer eine Grundaussage, die mir sehr bekannt vorkommt weil ich selber lange gebraucht habe um diese zu überwinden. Ich meine die Einstellungen das dann, wenn man sich vom "Mainstream" unterscheidet man ja "besser" ist als der Mainstream. Man ist ja ein Vordenker weil man als einer der Wenigen, vielleicht sogar als Einziger die Wahrheit erkannt hat und alle anderen einfach noch nicht weit genug sind und es deswegen ablehnen.

    Ja, je größer die Ablehnung der Anderen ist, desto mehr sieht man sich sogar in seiner eigenen Meinung bestätigt. Überlegen wir nur mal zurück, die ersten Menschen die behauptet haben die Sonne würde sich um die Erde drehen und nicht umgekehrt wurden damals sogar noch als Ketzer verbrannt. Dabei zeigt die Geschichte doch das sie nur geniale Vordenker waren, Ihrere Zeit weit vorraus. Hätten die anderen nur auf sie gehört, wäre das doch viel besser gewesen.

    Dies mag nur eine INterpretation sein, aber ich werde das Gefühl nciht los das Xin sich als einer dieser Vordenker sieht, gerade _weil_ ein Großteil der Programmierer sein Denkmodell ablehnen.

    Es gibt da aber Problem. Auch heute gibt es noch (oder wieder) Menschen die daran glauben die Sonne würde sich um die Erde drehen, womit sie ja komplett _gegen_ die allgemein verbreitete Meinung stehen die Erde würde sich tatsächlich um die Sonne drehen. Alle Beweise, daß dem nicht so sei wie z.B. der Mondflug und die daraus gewonnenen Erkenntnisse werden kurzerhand als Lügen hingestellt. Die Frage ist nun, sind diese Menschen, die sich ja definitiv vom Mainstream abheben und von sich selber ebenfalls glauben als Einzige die Wahrheit zu sehen, sind das jetzt unsere "Vordenker" ?

    Ich bin in diesem Thread nicht der erste der darauf Hinweis das Quantität keine Aussage über den Wahrheitsgehalt einer Theorie macht. Auch wenn wir alle der gleichen Meinung sind können wir falsch liegen. Aber umgekehrt gilt ebenso, daß auch dann, wenn wir mit unsere Meinung alleine stehen diese falsch sein kann.

    Was mich an Xin stutzig werden lässt ist das Gefühl, daß er gar nciht erst zu versuchen scheint die anderen Standpunkte verstehen zu wollen, weil für ihn ja von vorneherein klar ist das diese falsch sind. Vielmehr geht es ihm nur darum darzustellen _warum_ alle anderen Aussagen falsch und seine doch richtig ist.

    Ich behaupte, keine Seite ist wirklihc falsch. Jeder sieht die Welt mit seinen Augen und wenn die doch sehr ungewöhlnliche Sichtweise von Xin ihm dabei hilft gute Software zu schreiben, well, so be it. Trotzdem wäre es vielleicht ein Denkansatz, daß "die Andern" hier im board vielleicht ebenfalls mit ihrere Sichtweise gar nicht so falsch liegen, das eine gewisse Koexsistenz verschiedener Sichtweisen möglich sein könnte bei der es nicht darum geht, die jeweils andere als "falsch" hinzustellen sondern darum, auch die andere Sichtweise zu begreifen unabhängig davon ob man sie nun für sich selbst annimmt oder nicht.

    Andernfalls lebt man in einer sehr einsamen Welt weil man früher oder später nicht mehr in der Lage ist sich mit den anderen zu verständigen oder sie zu verstehen.

    Naja, sorry für das posting, ich wollte das seit Tagen loswerden.



  • Xin schrieb:

    Ich sehe da in keinerlei Hinsicht irgendwas abstraktes im Sinne von OOP in Deiner Definition.

    Das Konzept "Shape", dass siehst du sehr wohl - denn du willst sofort wie du den Code gesehen hast eine abstrakte Klasse Shape einbauen. Ich behaupte nun: man muss diese abstrakte Klasse nicht einbauen - da sie von der Idee her bereits im Code vorhanden ist.

    abstrakt im Sinne wie "Liebe" ein abstraktes Nomen ist. Nicht abstrakt im Sinne von Java Klassen.

    Shade Of Mine schrieb:

    Das ist dynamisch, aber nicht OOP. Neue Templates ändern nicht die Typen vorhandener Daten.

    Den Typen vorhandener Daten ändert sowieso nichts.

    Shade Of Mine schrieb:

    Stimmt, ich kann das Programm zur Laufzeit umschreiben. Das ist dann nicht mehr statisch, aber wenn ich das Programm umschreibe und so nachträglich OOP einfüge oder zur Laufzeit entferne ist das Ändern des Programms nicht OOP, sondern Reflection.

    Nein. Stell dir einen C++ Interpreter vor.
    Ist #include<foo.h> Reflection? Nein - es passiert nichts was nicht auch zur Compiletime passiert - denn Runtime ist gleich Compiletime.

    Selbstmodifizierender Code ist eine sehr alte Geschichte und gab's schon lange, bevor es mit Reflection standardisierte Interfaces dafür gab. Hier wird allerdings mit keinem Objekt gearbeitet, sondern der Code verändert.

    Wo ziehst du sowas immer her? Habe ich je von Reflection oder Selbstmodifizierendencode gesprochen? NEIN!

    Shade Of Mine schrieb:

    Ähh... hier muss ich leider widersprechen.. Ein Java Interface entspricht einer Klasse ohne Daten und ausschließlich abstrakten Funktionen.

    Danke, aber ich kann besser Java als du.

    Sag mir was der Java Code mit dem Interface mehr kann als die Template Variante.

    Wenn wir von "virtual" reden, dann meinen wir auch das Konzept von virtuellen Funktionen - klar kommt in Java das Wort virtual nicht vor. Aber in JavaScript hast du das komplette Konzept von virtuellen Funktionen nicht. Deshalb auch noch die kleine Frage: kann man in JavaScript Objektorientierte Programme schreiben?

    Ich kann mich nur wiederholen: vergiss bitte Java und C++. Die meisten hier kennen sich mit Java und C++ gut genug aus - vermutlich besser als du - du musst uns also nicht erklären was ein Interface ist.

    Ein großes Problem in dieser Diskussion ist der Punkt, dass dir Wissen fehlt. Bestes Beispiel ist: JavaScript unterstützt keine virtuellen Funktionen. Damit kann kein JavaScript Code in deinen Augen OO sein.

    Wenn wir nun aber folgenden Code betrachten:

    function Lampe(energiequelle) {
      this.quelle = energiequelle;
    }
    
    function Dynamo() {
      this.get_energie = function(){}
    }
    function Atomreaktor() {
      this.get_energie = function(){}
    }
    
    lampe = new Lampe(new Dynamo());
    

    dann macht dieser Code exakt das selbe wie der Java Code:

    class Lampe { public Lampe(Energiequelle e) {} }
    interface Energiequelle { abstract void get_energie(); }
    class Dynamo implements Energiequelle { public void get_energie(){} }
    class Atomreaktor implements Energiequelle { public void get_energie(){} }
    
    lampe = new Lampe(new Dynamo());
    

    Ich kann in JavaScript garkeine "Klasse" Energiequelle einbauen - die Sprache würde es nicht unterstützen - ich müsste hacks verwenden damit das halbwegs gut läuft.

    Was bei diesem Code aber viel wichtiger ist, ist nicht die Implementierung - denn die Implementierung hängt sowieso komplett von der Plattform ab. Mehr dazu weiter unten.

    Das wichtige ist die Idee und die Aussage des Codes. Beide lösen ein Problem:
    Ich habe eine Lampe und habe unendlich viele Energiequellen die ich beliebig kombinieren will.

    Beide Codes lösen diese Problemstellung auf exakt die selbe Art und Weise.

    Erst wird eine Schablone für Lampe Objekte erstellt und in dieser Schablone wird vermerkt dass es Energiequellen gibt. Und es wird ebenfalls vermerkt, wenn die Lampe Energie braucht, muss sie "get_energie" von der Energiequelle aufrufen.

    Beide Codes machen exakt dies. Für Leute wie dich, die nur Java/C++ kennen ist die Idee kein Interface zu haben erschreckend. Für Leute die nur JavaScript kennen ist die Idee ein Interface Energiequelle zu haben erschreckend.

    Man darf hier nie auf die Implementierung oder die Syntax achten - denn unterschiedliche Sprachen sehen unterschiedlich aus. In C++ sähe es uU so aus:

    template<typename Energiequelle>
    class Lampe {
    public:
      Lampe(Energiequelle* e);
    };
    
    class Dynamo { public: void get_energie() {} };
    class Atomreaktor { public: void get_energie() {} };
    

    Und auch hier wird wieder das exakt selbe gemacht. Lediglich die Tools die ich habe um diesen Sachverhalt auszudrücken unterscheiden sich.

    Das ist der essentielle Punkt: virtuelle Funktionen sind eine Technik um ein bestimmtes Problem zu lösen. Nämlich das Problem, dass ich nicht von vornherein weiß welches Verhalten ich will. Ich die Entscheidung über das Verhalten also einer Funktion übergebe die ich während ich meinen Teil des Codes schreibe nicht kenne.

    Wenn ich Lampe schreibe weiß ich, dass ich irgendwie Energie brauche. Ich weiß aber nicht wie ich an Energie ran komme. Ich lagere also "get_energie" aus und packe es in Energiequelle. Ich weiß zu dem Zeitpunkt wo ich Lampe implementiere nicht was es für Energiequellen gibt. Wichtig ist dabei: wenn es endlich Kaltefusion gibt, muss meine Lampe damit laufen.

    Jetzt kann man eben ein Interface Energiequelle nehmen und sagen: jede Energiequelle muss das Interface implementieren - und über dynamisches dispatching erkennt die Plattform auf der ich arbeite welche get_energie() Funktion nun die richtige ist.

    Ich kann aber auch eine andere Technik verwenden. Ich behaupte: "alles was mir mit get_energie() Energie liefert - taugt als Energiequelle". Meine Plattform erkennt Anhand des Typen der Energiequelle (der erst zur Runtime feststeht) welche Funktion "get_energie()" aufgerufen werden muss.

    Exakt das selbe Konzept - lediglich eine andere Implementierung.

    Das bringt mich auf das Problem der Implementierungen im allgemeinen. Wie eine Technik implementiert ist, hängt von der unterliegenden Plattform ab. zB würde ein C++ Compiler dein nutzloses interface "Energiequelle" einfach wegoptimieren da es nur sinnloser Ballast ist und keinen Mehrwert bietet. Wann instanziierungen stattfinden - definiert ebenfalls die Plattform. C++ Templates werden zwar von den aktuellen Compilern während der Compiletime instanziiert. Aber ein C++ Interpreter kompiliert ja zur Laufzeit. Das hat absolut nichts mit Reflection zu tun - es wird ja nichts zur Sprache C++ hinzu erfunden. Es wird lediglich die Compiletime etwas verschoben: nämlich zur Runtime.

    C# funktioniert zB genau so. Generics werden während der Runtime gecheckt und gegebenenfalls neue Generic-Klassen erstellt wenn ein neuer Typ aufgetaucht ist. Da kommt keine Reflection vor - es ist einfach so, dass die Kompilierung größtenteils während der Laufzeit stattfindet.

    Das komplette Konzept von Compiletime vs Runtime ist durch die modernen VMs von .NET und Java auf den Kopf gestellt worden. Kompilierungen finden zur Laufzeit statt - wenn wir also sagen Templates sind statisch, ist das eine Vereinfachung für uns aber kein Gesetz. Template könnten problemlos zur Laufzeit kompiliert werden - wie es zB C++ Interpreter tun. Wann instanziierungen stattfinden hängt also komplett von der Plattform ab auf der man arbeitet.

    Der Punkt auf den ich hinaus will: eine festklammerung an "dynamischen" Sachen um OOP zu definieren muss fehlschlagen, denn heutztage kann _alles_ dynamisch sein. In Sprachen wie JavaScript oder Java findet die Kompilierung auf den meisten Plattformen zur Laufzeit statt.

    Mit Plattform meine ich das System mit dem man entwickelt: zB C++ Compiler und Laufzeitbibliothek. Oder Java-Compiler + Java VM.

    Solange du es nicht schaffst Implementierungen und Konzepte zu trennen - wirst du uns nie verstehen. Das Konzept von Polymorphie kann ich auf unzählige Arten implementieren. Du klammerst dich an der gängigsten Implementierung - virtuelle Funktionen - fest. Aber es ist eben nur ein möglicher Ansatz dieses Konzept zu implementieren.

    Multimethods sind zB eine andere Implementierung der Idee dass sich Hund bellen sollte wenn ich ihm sage "gib_laut" aber eine Katze vielleicht doch "miau" machen sollte.

    C++ Templates stellen eine weitere Möglichkeit da dieses Konzept zu implementieren.

    Alle diese Implementierungen oder Lösungen gehen das selbe Problem an. Sie haben unterschiedliche stärken und schwächen - lösen aber allesamt das selbe Problem.



  • Templates sind keine Interfaces, Templates sind eine Abstraktionsebene höher, so könntest Du mit z.B. Templates Interfaces erstellen.

    Templates sind keine Interfaces. Templates sind wieder eine ganz andere Baustelle.

    Klar, templates sind eine Abstraktionsebene höher, aber für uns spielt das keine Rolle, weil unsere Definition von OOP auch eine Abstraktionsebene höher ist. Unsere Definition befindet sich nicht auf Sprachebene. Wir kennen zwar den Begriff "Abstraktes Interface", aber dieser Begriff ist in seiner implementation nicht definiert.

    Schau dir einmal UML Diagaramme an. Diese visualisieren am ehesten, was wir als OOP bezeichnen. UML wurde dafür entwickelt, um die Abstraktion die bei der OOA und OOD entsteht sinnvoll aufs papier zu bringen. In UML gibt es Objekte und ihre Abhängigkeiten untereinander. Man kann Interfaces erstellen, Objekte vererben, Polymorphie betreiben...Am Ende stellt UML das Graphisch dar, was ich als "Vertrag" bezeichnet habe und andere als das herumreichen von Nachrichten bezeichnen. Es gibt sogar UML interpreter die auf Basis dieser Diagramme und ein paar Codeschnipseln das Programm simulieren können - nicht in der funktionalität, es verarbeitet nichts, aber im Zusammenspiel der Objekte.
    Das wichtige ist aber, dass diese UML Diagramme nur ein Modell sind. Wie man das ganze hinter Umsetzt, ist bei jeder Sprache und jedem Projekt anders. Wichtig ist nur, dass am Ende das Programm mithilfe der Diagramme noch nachvollzogen werden kann. Bei manchen sprachen geht eine 1:1 umsetzung der Objekthierarchie, grundsätzlich also alle sprachen die Vererbung und Kapselung unterstützen. das ist aber noch lange keine pflicht das zu machen.

    pseudouml:

    -----------------|     |---------|  
    |  Klasse1       |     | Klasse2 |
    |----------------|     |---------|
    |  Member        |<----|....     |
    |----------------|     |---------|
    |Klasse1(Member1)|     |         |
    |function()      |     |foo()    |
    |________________|     |---------|
                          /         \
                         /           \
                        /             \
                 |-----------|      |-----------|
                 |Konkret1   |      |Konkret2   |
                 |...        |      |...        |
                 |-----------|      |-----------|
                 |foo()      |      |foo()      |
                 |-----------|      |-----------|
    

    Das ist nach unserer Definition ein Modell für ein OOP Programm. Teste es mal nicht an deiner definition, sondern schau dir das an. Klasse1 hat ein Member das das Interface Klasse2 hat. Es können aber 2 Konkrete Objekte dafür in frage kommen.

    Implementation in C++

    //1
    template<class Klasse2>
    class Klasse1
    {
        private:
            Klasse2 member;
        public:
            Klasse1(const Klasse2& member);
            void function();
    };
    class Konkret1
    {
        public:
            void foo();
    };
    class Konkret2
    {
        public:
            void foo();
    };
    
    ...
    Klasse1<Konkret1> x(Konkret1());
    Klasse1<Konkret2> y(Konkret2());
    
    //2
    class Klasse2
    {
        public:
            virtual void foo()=0;
    };
    class Klasse1
    {
        private:
            Klasse2* member;
        public:
            Klasse1(Klasse2* member)
            void function();
    };
    class Konkret1:public Klasse2
    {
        public:
            void foo();
    };
    class Konkret2:public Klasse2
    {
        public:
            void foo();
    };
    
    Klasse1 x(new Konkret1());
    Klasse1 y(new Konkret2());
    

    Beide Implementationen sind mit dem UML Diagramm problemlos nachvollziehbar. Wann man eine der versionen wählt, ist Situationsabhängig.
    Natürlich sind auch umsetzungen von UML Diagrammen in anderen Sprachen möglich, sogar in C geht das. Die Frage, ob die eine Funktion OOP ist und die andere nicht, lässt sich dann so beschreiben: Gibt es ein Programmmodell, in dem diese Funktion ein sinnvolles Member einer Klasse sein kann(oder bei einem bekannten programmmodell: passt diese Funktion in irgendeine definition?)?

    UML ist leider nicht das maß aller Dinge, weil es auf die Mainstreamsprachen zugeshcnitten ist, andere Sprachen sind damit nicht sehr glücklich, die umsetzungen sind zwar möglich, aber bestimmte Sachen kann man in UML nicht darstellen, die in diesen Sprachen möglich sind, zb dynamisches ändern des Interfaces durch hinzufügen von methoden(oder in C++ vererben von typlisten um eine dynamische Menge von Interfaces zu vererben).

    //nachtrag Deswegen wurde UML auch bisher nicht genannt. Der Prozess beginnt im Kopf, wie man es visualisiert ist jedem selbst überlassen, oder wird mit dem team abgesprochen. es ist auch möglich, dass es nur kurze notizen dazu gibt, oder kommentare im Programmcode,oder ...

    //nachtrag2:
    Wann ist ein Code nicht OO, immerhin kann man bei genügend großem willen überall ein Modell finden:

    Es ist schwer zu sagen: diese funktion ist nicht OO. Das ist klar. Aber man kann sagen: die Verwendung dieser Funktion ist nicht OO,oder der funktionskern. Beispiel STL algorithmen. Prinzipiell könnten sie alle member eines Interfaces mit namen "Container" sein. Jeder container hat dann zb sein sort.

    Auch die Argumente der funktion sind Objekte. Ein iterator ist ein konzept, selbst wenn er in dieser implementation ein zeiger ist, tut das keinen Abbruch.
    Auch die übergebenen funktoren sind ein Konzept und streng genommen auch OO.

    Aber die verwendung ist funktionale programmierung:

    std::vector<int> vec;
    ...
    //alle member mithilfe einer lambda funktion quadrieren und das Ergebnis in einen neuen vector kopieren
    std::vector<int> sqares;
    std::transform(vec.begin(),vec.end(),std::back_insert_iterator<vector<int> >(squares),_1*=_1);
    

    oder das hier:

    a.foo()
    b=a.bar();
    if(a.doSth())
    {
        b.blub();
        a.setBar(b);
    }
    ...
    

    das ist ganz klar prozedurale Programmierung, weil man angibt was das programm in welcher reihenfolge zu tun hat- selbst wenn jede aufgerufene funktion virtuell ist. Aber jede funktion und jedes Objekt hierbei ist OOP.

    //nachtrag3:
    wenn //1 kein OOP für dich ist, was ist es eigentlich dann?



  • Zum Thema Definition von OOP: http://lambda-the-ultimate.org/node/2386 [...]

    edit: Ups, Duplikat. Ihr schreibt aber auch wirklich viel und lang hier 😉



  • @bashar siehe rüigers post 🙂


Anmelden zum Antworten