Vererbung & Polymorphie anhand von Beispiel erklären



  • Sqw4n schrieb:

    Welche Sprachen werden das? Würde gerne mal rein schauen wie das machen. Irgendwo muss ja auch da die Bindung sein.

    z.B. JavaScript/ECMAScript
    Bzw. allgemein alles was hier rein fällt (und nicht zusätzlich noch Klassen hat): http://en.wikipedia.org/wiki/Prototype-based_programming



  • Sqw4n schrieb:

    TyRoXx schrieb:

    Später im Artikel steht dann der Widerspruch:

    http://de.wikipedia.org/wiki/Objektorientierte_Programmierung schrieb:

    Die ISO-Definition gilt inzwischen im Allgemeinen als zu vereinfachend, da auch klassenlose objektorientierte Sprachen existieren und auch der Vererbung inzwischen weniger Bedeutung beigemessen wird als noch in den 1990ern.

    Welche Sprachen werden das? Würde gerne mal rein schauen wie das machen. Irgendwo muss ja auch da die Bindung sein.

    So ziemlich jede Sprache, die Closures hat. Beispielsweise in Lua werden Closures nicht aus Klassen erzeugt, können nichts erben und sind nicht polymorph. Sie sind aber Objekte im Sinne von OOP.

    local state = "private"
    -- Konstruktion eines Objektes
    local print_hello = function ()
    	-- das Objekt bekommt genau eine Methode
    	print("Hello, I am an object!")
    	print("And I have " .. state .. " parts.")
    end
    
    -- virtueller Methodenaufruf
    print_hello()
    
    Hello, I am an object!
    And I have private parts.
    

    hustbaer schrieb:

    TyRoXx schrieb:

    EDIT: Ich weiß gerade gar nicht was dein Problem ist. (...)

    Mein Problem ist, dass du ein Phrasendrescher bist, der mich (und andere) - auf reichlich grosskotzige Art - mit haltlosem Unsinn "korrigiert".

    Ach, und was machst du?



  • lol



  • TyRoXx schrieb:

    hustbaer schrieb:

    TyRoXx schrieb:

    EDIT: Ich weiß gerade gar nicht was dein Problem ist. (...)

    Mein Problem ist, dass du ein Phrasendrescher bist, der mich (und andere) - auf reichlich grosskotzige Art - mit haltlosem Unsinn "korrigiert".

    Ach, und was machst du?

    Wenn es etwas gibt, was ich in diesem Forum gelernt habe, dann dass es viele Ansichten gibt, die nicht alle richtig sein können. Was ich im Studium gelernt habe, ist dass es für jede beliebige Ansicht, egal wie idiotisch sie ist, auch eine Quelle zu finden ist - notfalls im Informatikduden, da steht alles drin, inkl. dem Gegenteil von dem, was im Informatikduden steht. Belegen kann man alles.

    Ich bin häufig anderer Ansicht als die Mehrheit und ich bin durchaus der Auffassung, dass hier viel Halbwissen präsentiert wird - und ich würde auf keinen Fall sagen, dass ich zwangsläufig richtig liege, ich schließe das lediglich mal daraus, dass eben nicht alle Recht haben können. Manche Standpunkte sind aber durchdachter als andere. Ich zähle mich aber durchaus zu den Leuten, die ihren Standpunkt lange abwägen.

    Und so sollte man gerade die Standpunkte, die "totaler Blödsinn" sind, durchaus mal als Inspiration auffassen und hoffen, dass das Gegenüber auch einen Grund hatte, zu seiner Überzeugung zu kommen und nur nicht die richtigen Worte fand, das einem selbst günstig zu erklären. Neben der Möglichkeit, dass jemand das Konzept nicht verstanden hat, gibt es auch die Möglichkeit, dass er etwas verstanden hat, was man selbst noch nicht überlegt hat.
    Manchmal haben alle intelligente Konzepte, aber keine intelligenten Vokabeln für ihre Ideen.

    Ich kann nur sagen, dass in der Informatik viele Vokabeln eher wie Floskeln ("It's raining cats and dogs") benutzt werden und weniger wie Beschreibungen einer Eigenschaft. Interpreter und Compiler zum Beispiel: Jeder Compiler ist zwangsläufig ein Interpreter. Die meisten Interpretersprachen sind Bytecode-Compiler. Zwei nichtsaussagende Begriffe werden benutzt, um 10 Klassen von Programmiersprachen zu bescheiben - über solch schwammige Begriffe tauscht man sich in der Informatik aus. Das kann nicht sinnvoll funktionieren.

    "Objektorientierte Programmierung" steht auf dieser Liste schwachsinniger Begriffe ganz weit oben, da sich die OOP in den populären Sprachen wie C++, C#, Java... definitiv einen Scheiß um das Objekt selbst kümmert, sondern lediglich um den Datentyp des Objektes. Es ist "Datentyp-orientierte Programmierung", darum nennen wir es "Objektorientiert"...!?
    Ein Tier kann einen gibLaut() geben, aber ein Hund macht immer "Wau!". Zwei Objekte vom Datentyp Hund hingegen müssten einen Member haben, der den Algorithmus zum Bellen beschreibt. Würde man sich um an den einzelnen Objekte orientieren, bräuchte man Funktionpointer statt vtables, damit der eine Hund zur <wortspiel>Laufzeit</wortspiel> "Wau!" und der andere "Wa-Uff!" bellen kann.
    Der eine Hund bellt immer, der andere bringt in Abhängigkeit zur Laufstrecke keinen Ton mehr raus.

    Das leistet OOP in den "objektorientierten Sprachen" aber gar nicht, weil OOP sich am Datentyp orientiert und für datentyporientierte Programmierung benötigt man nunmal Vererbung der Datentypen.
    Das Closure-Beispiel (ich kann kein Closure) erscheint mir ein Funktionpointer darzustellen, orientiert sich also offenbar am Objekt.

    Der eine definiert DataHiding als Teil von OOP, ich wüsste nicht, wieso das erforderlich wäre, schließlich kann C OOP, aber kein Datahiding. Aber wenn das einer für wichtig hält... gut. Das dann OOP zu nennen... naja...

    Auch funktionale Programmiersprachen benötigen Vererbung. Nur, dass man sie nicht selbst sieht, weil das Interface nicht vom Entwickler vererbt wird, sondern implizit von der Sprache. Es muss eine Methode geben, die eine Liste beispielsweise fragt, ob sie die Eigenschaften erfüllt, um einen entsprechenden Zweig des Algorithmus' auszuführen. Im Closure-Beispiel wäre da die Frage, ob "print_hello()" eine aufrufbare Funktion des Objektes ist und die Aufgabe, eben dieses zu tun. Nur weil der Entwickler diese impliziten Sachen nicht sieht, nicht explizit formuliert, heißt das nicht, dass sie nicht implizit da sind.

    Missverständnisse sind also vorprogrammiert, weil viel zu viele Ideen und Konzepte unter einem in der Regel irreführenden Namen zusammengepanscht werden und jeder irgendjemanden finden kann, der das genauso geht und das in den Informatikduden, Wikipedia oder sonstwohin geschrieben hat.

    Irgendjemanden zu zitieren bedeutet nicht, dass der Zitierte etwas sinnvolles geschrieben hat.
    In diesem Sinne, lasst euch einfach voneinander inspirieren und vermeidet feststehende Begriffe, die jeder nach Belieben auslegt, sondern erklärt euch. Und wenn sich jemand die Mühe macht, sich zu erklären, lest es und sucht nicht nur, was eurer Meinung widerspricht, sondern auch, was eure Erkenntnis erweitert.



  • Nachdem dieser Thread ja ohnehin nichts mehr mit dem Startpost zu tun hat: Koennte sich jemand die Muehe machen, mir zu erklaeren, was diese "echte" OOP ist? Offensichtlich habe ich weder in C++, noch in Java jemals "OOP" programmiert, obwohl ich Klassen eingesetzt habe, da diese Sprachen ja keine OOP "im eigentlichen Sinne" unterstuetzen. Ich wuerde mich daher ueber die Erleuchteung freuen, was nun diese "echte OOP" sein soll, die C++ nicht unterstuetzt. Am besten anhand eines C++-Beispiels erklaert, wo man sieht, was fehlt, damit ich mir nicht erstmal irgendeine andere Sprache ansehen muss, um das zu verstehen.



  • Kellerautomat schrieb:

    Nachdem dieser Thread ja ohnehin nichts mehr mit dem Startpost zu tun hat: Koennte sich jemand die Muehe machen, mir zu erklaeren, was diese "echte" OOP ist?

    Ein Konzept, das stets von belehrenden Laien verbreitet wird, gehört in die esoterische Ecke der Informatik. Ein sehr guter Indikator, daß es gar keinen Zweck hat, sich mit dieser Person weiter fachlich zu unterhalten.



  • Xin schrieb:

    TyRoXx schrieb:

    hustbaer schrieb:

    TyRoXx schrieb:

    EDIT: Ich weiß gerade gar nicht was dein Problem ist. (...)

    Mein Problem ist, dass du ein Phrasendrescher bist, der mich (und andere) - auf reichlich grosskotzige Art - mit haltlosem Unsinn "korrigiert".

    Ach, und was machst du?

    Wenn es etwas gibt, was ich in diesem Forum gelernt habe, dann dass es viele Ansichten gibt, die nicht alle richtig sein können. Was ich im Studium gelernt habe, ist dass es für jede beliebige Ansicht, egal wie idiotisch sie ist, auch eine Quelle zu finden ist - notfalls im Informatikduden, da steht alles drin, inkl. dem Gegenteil von dem, was im Informatikduden steht. Belegen kann man alles.

    Ich bin häufig anderer Ansicht als die Mehrheit und ich bin durchaus der Auffassung, dass hier viel Halbwissen präsentiert wird - und ich würde auf keinen Fall sagen, dass ich zwangsläufig richtig liege, ich schließe das lediglich mal daraus, dass eben nicht alle Recht haben können. Manche Standpunkte sind aber durchdachter als andere. Ich zähle mich aber durchaus zu den Leuten, die ihren Standpunkt lange abwägen.

    Und so sollte man gerade die Standpunkte, die "totaler Blödsinn" sind, durchaus mal als Inspiration auffassen und hoffen, dass das Gegenüber auch einen Grund hatte, zu seiner Überzeugung zu kommen und nur nicht die richtigen Worte fand, das einem selbst günstig zu erklären. Neben der Möglichkeit, dass jemand das Konzept nicht verstanden hat, gibt es auch die Möglichkeit, dass er etwas verstanden hat, was man selbst noch nicht überlegt hat.
    Manchmal haben alle intelligente Konzepte, aber keine intelligenten Vokabeln für ihre Ideen.

    Ich kann nur sagen, dass in der Informatik viele Vokabeln eher wie Floskeln ("It's raining cats and dogs") benutzt werden und weniger wie Beschreibungen einer Eigenschaft. Interpreter und Compiler zum Beispiel: Jeder Compiler ist zwangsläufig ein Interpreter. Die meisten Interpretersprachen sind Bytecode-Compiler. Zwei nichtsaussagende Begriffe werden benutzt, um 10 Klassen von Programmiersprachen zu bescheiben - über solch schwammige Begriffe tauscht man sich in der Informatik aus. Das kann nicht sinnvoll funktionieren.

    "Objektorientierte Programmierung" steht auf dieser Liste schwachsinniger Begriffe ganz weit oben, da sich die OOP in den populären Sprachen wie C++, C#, Java... definitiv einen Scheiß um das Objekt selbst kümmert, sondern lediglich um den Datentyp des Objektes. Es ist "Datentyp-orientierte Programmierung", darum nennen wir es "Objektorientiert"...!?
    Ein Tier kann einen gibLaut() geben, aber ein Hund macht immer "Wau!". Zwei Objekte vom Datentyp Hund hingegen müssten einen Member haben, der den Algorithmus zum Bellen beschreibt. Würde man sich um an den einzelnen Objekte orientieren, bräuchte man Funktionpointer statt vtables, damit der eine Hund zur <wortspiel>Laufzeit</wortspiel> "Wau!" und der andere "Wa-Uff!" bellen kann.
    Der eine Hund bellt immer, der andere bringt in Abhängigkeit zur Laufstrecke keinen Ton mehr raus.

    Das leistet OOP in den "objektorientierten Sprachen" aber gar nicht, weil OOP sich am Datentyp orientiert und für datentyporientierte Programmierung benötigt man nunmal Vererbung der Datentypen.
    Das Closure-Beispiel (ich kann kein Closure) erscheint mir ein Funktionpointer darzustellen, orientiert sich also offenbar am Objekt.

    Der eine definiert DataHiding als Teil von OOP, ich wüsste nicht, wieso das erforderlich wäre, schließlich kann C OOP, aber kein Datahiding. Aber wenn das einer für wichtig hält... gut. Das dann OOP zu nennen... naja...

    Auch funktionale Programmiersprachen benötigen Vererbung. Nur, dass man sie nicht selbst sieht, weil das Interface nicht vom Entwickler vererbt wird, sondern implizit von der Sprache. Es muss eine Methode geben, die eine Liste beispielsweise fragt, ob sie die Eigenschaften erfüllt, um einen entsprechenden Zweig des Algorithmus' auszuführen. Im Closure-Beispiel wäre da die Frage, ob "print_hello()" eine aufrufbare Funktion des Objektes ist und die Aufgabe, eben dieses zu tun. Nur weil der Entwickler diese impliziten Sachen nicht sieht, nicht explizit formuliert, heißt das nicht, dass sie nicht implizit da sind.

    Missverständnisse sind also vorprogrammiert, weil viel zu viele Ideen und Konzepte unter einem in der Regel irreführenden Namen zusammengepanscht werden und jeder irgendjemanden finden kann, der das genauso geht und das in den Informatikduden, Wikipedia oder sonstwohin geschrieben hat.

    Irgendjemanden zu zitieren bedeutet nicht, dass der Zitierte etwas sinnvolles geschrieben hat.
    In diesem Sinne, lasst euch einfach voneinander inspirieren und vermeidet feststehende Begriffe, die jeder nach Belieben auslegt, sondern erklärt euch. Und wenn sich jemand die Mühe macht, sich zu erklären, lest es und sucht nicht nur, was eurer Meinung widerspricht, sondern auch, was eure Erkenntnis erweitert.

    Darfst nicht "objektorientiertes Programmieren" (gibt es) und "objektorientierte Sprache" (gibt es nicht) vermischen und daraus eine Definition von "objektorientiert" zusammenmixen.



  • Xin schrieb:

    Missverständnisse sind also vorprogrammiert, weil viel zu viele Ideen und Konzepte unter einem in der Regel irreführenden Namen zusammengepanscht werden und jeder irgendjemanden finden kann, der das genauso geht und das in den Informatikduden, Wikipedia oder sonstwohin geschrieben hat.

    OOP an sich ist ein einfaches Konzept.
    OOP als Buzzword ist sehr unübersichtlich und widersprüchlich. OOP war mal der neueste Schrei -> jeder schrieb an seine Sprache OOP dran -> alle Features dieser Sprachen wurden auf einmal als unverzichtbar für OOP beworben.
    Java nannte sich "objektorientierte Programmiersprache", weil es ein paar Features hat, die einem bei OOP helfen (vor allem virtuelle Methoden und der Garbage Collector). Man kann mit Java auch wunderbar objektorientiert programmieren. Muss man aber nicht. Andersherum kann man auch ohne "objektorierte Programmiersprache" OOP machen wie in C.

    Kellerautomat schrieb:

    Nachdem dieser Thread ja ohnehin nichts mehr mit dem Startpost zu tun hat: Koennte sich jemand die Muehe machen, mir zu erklaeren, was diese "echte" OOP ist? Offensichtlich habe ich weder in C++, noch in Java jemals "OOP" programmiert, obwohl ich Klassen eingesetzt habe, da diese Sprachen ja keine OOP "im eigentlichen Sinne" unterstuetzen. Ich wuerde mich daher ueber die Erleuchteung freuen, was nun diese "echte OOP" sein soll, die C++ nicht unterstuetzt. Am besten anhand eines C++-Beispiels erklaert, wo man sieht, was fehlt, damit ich mir nicht erstmal irgendeine andere Sprache ansehen muss, um das zu verstehen.

    War ich das, der angeblich geschrieben hat, dass C++ keine OOP unterstützt?

    volkard schrieb:

    Kellerautomat schrieb:

    Nachdem dieser Thread ja ohnehin nichts mehr mit dem Startpost zu tun hat: Koennte sich jemand die Muehe machen, mir zu erklaeren, was diese "echte" OOP ist?

    Ein Konzept, das stets von belehrenden Laien verbreitet wird, gehört in die esoterische Ecke der Informatik. Ein sehr guter Indikator, daß es gar keinen Zweck hat, sich mit dieser Person weiter fachlich zu unterhalten.

    Anstatt hier rumzuheulen könntest du auch an der Diskussion teilnehmen. Was schreibe ich denn so für furchtbar Falsches?



  • Kellerautomat schrieb:

    Nachdem dieser Thread ja ohnehin nichts mehr mit dem Startpost zu tun hat: Koennte sich jemand die Muehe machen, mir zu erklaeren, was diese "echte" OOP ist?

    Da ist die Frage, wie Du "echte" OOP verstehst.
    Ich würde den Begriff "OOP" als Floskel in populären Sprachen verwenden, wenn Du Datentypen klassifizierst (daher das Schlüsselwort 'class') und entsprechend des Datentyps eines Objektes unterschiedliche Algorithmen aufrufst (quasi in dem Moment, wo virtuelle Funktionen auftauchen).

    Das kannst Du mit einer C-Funktion notfalls auch mit einem switch() lösen, so dass Du anhand eines Struktur-Members den einen oder anderen Algorithmus durchläufst.

    Kellerautomat schrieb:

    Offensichtlich habe ich weder in C++, noch in Java jemals "OOP" programmiert, obwohl ich Klassen eingesetzt habe, da diese Sprachen ja keine OOP "im eigentlichen Sinne" unterstuetzen. Ich wuerde mich daher ueber die Erleuchteung freuen, was nun diese "echte OOP" sein soll, die C++ nicht unterstuetzt. Am besten anhand eines C++-Beispiels erklaert, wo man sieht, was fehlt, damit ich mir nicht erstmal irgendeine andere Sprache ansehen muss, um das zu verstehen.

    Was mich angeht, konzentriere Dich auf den Begriff: OBJEKT-ORIENTIERT.

    Das kann man in zwei weisen verstehen: Die Perspektive des Entwicklers auf das Datenobjekt zu verlegen, dann reicht es für viele seine Funktionen in eine Klasse zu betten. Dann hast Du immernoch normale sturkturierte Programmierung, aber es steht halt "class" drumrum. Das verstehen manche Leute auch als OOP. Das kann man als Erklärung akzeptieren, aber das macht jeder brauchbare C-Programmierer auch. Von daher gibt es keinen Unterschied zwischen Fortran und Java. Die Erklärung führt also zu keinem Mehrwert, der ein so langes Buzzwort wert wäre.

    Ich begreife das umgangssprachlich genannte "Objekt-Orientiert" als den Wunsch das Feature, den Mehrwert, den C++ zu C besser unterstützt zu nutzen. Weswegen man Sprachen wie C# und Java als "Objektorientiert" bezeichnet.
    Das sind virtuelle Funktionen, die anhand des [Datentyps des] Objektes ausgewählt werden. Man orientiert sich am Datentyp(!) des Objektes, weswegen ich hier bevorzugt von "Datentyp-orientierter" Programmierung spreche - die man - übrigens vermeiden sollte, wann immer es geht, die aber eben eine sehr gute Standard-Lösung ist, um Designprobleme zu lösen, das reicht bereits, um sehr viele Probleme effizient zu lösen. Wenn man so ein Problem überhaupt hat.
    Eine Standard-Lösung bezeichne ich als Design-Pattern, nicht als Sprachparadigma und auch da gehen die Meinungen deutlich auseinander, obwohl man dem angeblichen OOP-Sprachparadigma auch keine Generation zuordnen kann, das OOP-Sprachparadigma also auch bei den Befürwortern eines Paradigmas eine Sonderrolle einnimmt, weil es nunmal einfach nicht passt. OOP ist immer auch imperative Programmierung, die ich ebenfalls als Fundament der funktionalen Programmierung einordne. Ob FP nun eine Einschränkung oder Weiterentwicklung von IP ist... je nach Bedarf stimmt beides.

    "Echte" Objekt-Orientierung orientiert sich am individuellen Objekt. Klingt logisch, weicht von der landläufigen Überzeugung ab! Die Entscheidung über den verwendeten Algorithmus fällt also nicht anhand des Datentyps für alle Objekte eines Datentyps gleich, sondern individuell für jede einzelne Objektinstanz. Vererbung (von virtuellen Funktionen/Interfaces) ist hierbei hilfreich/notwendig, damit man weiß, was man ein Objekt überhaupt fragen darf. Statt virtueller Funktionen, die in einer vtable gesammelt werden und nicht individuell anpassbar sind, müsste man in C++ individuell modifizierbare Funktionspointer erben.
    Das braucht man aber extrem selten. Von daher gehe ich tatsächlich davon aus, dass Du nie im Leben OOP programmiert hast.

    Datentyporientierte Programmierung unterstützt C++, in dem es virtuelle Methoden zur Verfügung stellt, die das automatische Anlegen der vtables unterstützt. In C ist das nervige Handarbeit.
    Funktionspointer hingegen haben eine unschöne Syntax, ob das als "Unterstützung" im Sinne von Hilfe für den Entwickler verstanden werden kann, würde ich nicht unterschreiben. Aber als "Unterstützung" im Sinne von 'Man kann es formulieren, wenn man Funktionspointer formulieren kann'. Man kann in C auch vtables formulieren, aber C unterstützt einen eben nicht dabei.

    Wenn man auf OOP und typ-orientierter Programmierung verzichten kann, dann sollte man das auch tun, denn die Indirektion kostet Zeit. Dabei ist TOP speichersparender (eine VTable pro Typ), aber langsamer (zweifach indirekt) als OOP (eine eingebettete VTable pro Instanz), aber schneller (einfach indirekt).
    Der Hype um TOP aka "OOP" ist sicherlich berechtigt, aber man sollte Typ-Orientierte-Programmierung (aka OOP) nicht per default verwenden (wie in Java), sondern nur bei echtem Bedarf (wie in C++), bzw. in Java per "final" abschalten.

    volkard schrieb:

    Darfst nicht "objektorientiertes Programmieren" (gibt es) und "objektorientierte Sprache" (gibt es nicht) vermischen und daraus eine Definition von "objektorientiert" zusammenmixen.

    Warum sollte es keine objektorientierten Sprachen geben? Nur C++, Java und C# sind in meinen Augen keine, da dies sinnvollerweise auch überhaupt nicht die Zielrichtung der Sprachen darstellt. Hier geht es darum - zumindet bei C++ - möglichst effizient zu arbeiten und das bedeutet, dass man Indirektionen vermeidet.

    Wenn Du bei Python aber Funktionen objektorientiert (also individuell für ein Objekt) zur Laufzeit hinzufügen und überschreiben kannst, dann würde ich Python als objektorientierte Sprache bezeichnen. Leider aber eben nicht annähernd so effizient wie C#, Java oder eben C++.

    TyRoXx schrieb:

    OOP an sich ist ein einfaches Konzept.
    OOP als Buzzword ist sehr unübersichtlich und widersprüchlich. ...
    Java nannte sich "objektorientierte Programmiersprache", weil es ein paar Features hat, die einem bei OOP helfen (vor allem virtuelle Methoden und der Garbage Collector).

    Dass der Garbage Collector jetzt zu OOP gehört höre ich jetzt tatsächlich zum ersten Mal.
    Warum gehört GC jetzt Deiner Meinung nach zu OOP?

    -----------

    PS: Vielleicht sollte man bei allen Sprachen mal überall "-unterstützend" ranschreiben. C++ ist eine Typ-orientierte-Programmierung-unterstützende Sprache. Auch in C++ kann man beliebige Funktionen zu einem Objekt hinzufügen, man muss nur von einem Dictionary mit Funktionspointern ableiten. Aber C++ unterstützt das eben nicht. Man kann also immer sehr viel mit Sprachen machen, aber bei manchen Sprachen passiert halt vieles implizit, was den Entwickler unterstützt, bei anderen nicht.



  • TyRoXx schrieb:

    Kellerautomat schrieb:

    Nachdem dieser Thread ja ohnehin nichts mehr mit dem Startpost zu tun hat: Koennte sich jemand die Muehe machen, mir zu erklaeren, was diese "echte" OOP ist? Offensichtlich habe ich weder in C++, noch in Java jemals "OOP" programmiert, obwohl ich Klassen eingesetzt habe, da diese Sprachen ja keine OOP "im eigentlichen Sinne" unterstuetzen. Ich wuerde mich daher ueber die Erleuchteung freuen, was nun diese "echte OOP" sein soll, die C++ nicht unterstuetzt. Am besten anhand eines C++-Beispiels erklaert, wo man sieht, was fehlt, damit ich mir nicht erstmal irgendeine andere Sprache ansehen muss, um das zu verstehen.

    War ich das, der angeblich geschrieben hat, dass C++ keine OOP unterstützt?

    Auch wenn Xin mich dazu bewegt hat, nachzufragen, spreche ich hier niemanden direkt an. Ich werfe die Frage viel mehr in den Raum, da ich das schon oefters von mehreren Seiten gehoert habe.



  • Ich weiß nicht mehr wer es geschrieben hat.
    Das JavaScript bsp. für OOP-Sprachen ohne klassen hat mich überzeugt.
    Allerdings erfolgt da auch klar eine Bindung an das Objekt.
    bei oeffneTuer(auto) wie es z.B. in C gehen würde sehe ich die Bindung aber nicht.

    Andersherum kann man auch ohne "objektorierte Programmiersprache" OOP machen wie in C.

    Könnte einer vllt ein ganz kurzes bsp. zeigen wie das dort funktioniert.
    Hab C vor 7 Jahren gelernt und seit 5 nicht mehr benutzt.

    "Objektorientierte Programmierung" steht auf dieser Liste schwachsinniger Begriffe ganz weit oben, da sich die OOP in den populären Sprachen wie C++, C#, Java... definitiv einen Scheiß um das Objekt selbst kümmert, sondern lediglich um den Datentyp des Objektes. Es ist "Datentyp-orientierte Programmierung", darum nennen wir es "Objektorientiert"...!?
    Ein Tier kann einen gibLaut() geben, aber ein Hund macht immer "Wau!". Zwei Objekte vom Datentyp Hund hingegen müssten einen Member haben, der den Algorithmus zum Bellen beschreibt. Würde man sich um an den einzelnen Objekte orientieren, bräuchte man Funktionpointer statt vtables, damit der eine Hund zur <wortspiel>Laufzeit</wortspiel> "Wau!" und der andere "Wa-Uff!" bellen kann.
    Der eine Hund bellt immer, der andere bringt in Abhängigkeit zur Laufstrecke keinen Ton mehr raus.

    gibLaut wird doch nicht in "Tier" implementiert. Es würde Tier geben. Hund würde von Tier erben. "SchaeferHund" würde von Hund erben. Und SchaeferHund hat eigentschaften (ausdauer, maxLaufGeschwindigkeit, sprungHoehe). Eine Methode "gibLaut()" wäre dann noch zu allgemein,(wäre aber ein guter name für ein Internetface). SchaeferHund bekommt also Methode Bellen, Jaulen und Knurren (und was man sonst noch so braucht. Und jede Methode berechnet dann intern anhand der Eiegenschaften des Objekts wie der Hund grade bellt. So können die auch komunizieren. Wenn man es nicht so genau braucht, dann kann man auch gibLaut implementieren und Bellen, Jaulen, Knurren ggf. an Hand von Parametern unterscheiden. Ein objekt wäre es dann aber dennoch.



  • Sqwan schrieb:

    bei oeffneTuer(auto) wie es z.B. in C gehen würde sehe ich die Bindung aber nicht.

    void Auto::oeffnetTuer( void )
    oder
    void oeffneTuer( struct Auto * this )

    Das erste Argument in C++ erklärt bei einer Methode immer die Bindung. Entsprechend wird das in C gerne ebenso gehandhabt. Um den Code zu einer Klasse zu machen, schreibt man "class" drumrum und entfernt das erste Argument der Funktionen. Fertig.

    Handelt es sich um eine Const-Methode lautet die Signatur
    void oeffneTuer( struct Auto const * this )

    Klassenorientierte(!) Programmierung ist keine Magie in C++, es ist nur eine etwas andere Schreibweise. Hier ist weiterhin alles statisch gebunden.

    Sqwan schrieb:

    Andersherum kann man auch ohne "objektorierte Programmiersprache" OOP machen wie in C.

    Könnte einer vllt ein ganz kurzes bsp. zeigen wie das dort funktioniert.
    Hab C vor 7 Jahren gelernt und seit 5 nicht mehr benutzt.

    Du kannst virtuelle Funktionen wie hier beschrieben in C nachbilden.
    Da sind zwar Klassen involviert, aber die vtables sind von Hand gebaut.
    Das ganze ist so also sehr leicht nach C übertragbar. Dass man die vtables nicht mehr von Hand bauen muss, ist die implizite Unterstützung, die C++ einem durch das Schlüsselwort "virtual" ermöglicht.
    C++ ist damit eine Sprache, die Datentyp-orientiertung (helfend) unterstützt, während C eine Sprache ist, mit der man auch Datentyp-orientiert programmieren kann.

    Sqwan schrieb:

    Xin schrieb:

    Der eine Hund bellt immer, der andere bringt in Abhängigkeit zur Laufstrecke keinen Ton mehr raus.

    gibLaut wird doch nicht in "Tier" implementiert. Es würde Tier geben. Hund würde von Tier erben. "SchaeferHund" würde von Hund erben.

    Vererbung gibt es zur Laufzeit nicht mehr.

    Dein Objekt vom Typ Hund müsste also zur Laufzeit objektindividuell seine vtable ändern, so dass gibLaut() auf einen anderen Algorithmus verweist. Die vtable ist immer für alle Objekte des Typs 'Hund' zuständig und daher statisch. Es muss also in C++ mit Funktionspointern gearbeitet werden, was gewissermaßen eine objekt-individuelle vtable darstellt, die modifiziert werden kann.
    So kann ein normaler Hund zur Laufzeit zum Schäferhund mutieren.

    Aber das Problem findet sich in der alltäglichen Anwendungsprogrammierung kaum.



  • Sqwan schrieb:

    Andersherum kann man auch ohne "objektorierte Programmiersprache" OOP machen wie in C.

    Könnte einer vllt ein ganz kurzes bsp. zeigen wie das dort funktioniert.
    Hab C vor 7 Jahren gelernt und seit 5 nicht mehr benutzt.

    #include <stdio.h>
    #include <stdlib.h>
    #include <stddef.h>
    
    /*die Schnittstelle:*/
    struct output_stream;
    
    typedef struct output_stream_vtable
    {
      /*eine virtuelle Methode*/
      size_t(*write)(struct output_stream *, char const *, size_t);
    
      /*ein virtueller Destruktor*/
      void(*destroy)(struct output_stream *);
    }
    output_stream_vtable;
    
    typedef struct output_stream
    {
      output_stream_vtable const *virtuals;
    }
    output_stream;
    
    /*etwas sugar für die Methodenaufrufe*/
    static size_t output_stream_write(output_stream *stream, char const *data, size_t size)
    {
      return stream->virtuals->write(stream, data, size);
    }
    
    static void output_stream_destroy(output_stream *stream)
    {
      stream->virtuals->destroy(stream);
    }
    
    /*eine Klasse, die die Schnittstelle implementiert*/
    typedef struct owning_file_output_stream
    {
      /*so erbt man*/
      output_stream base;
    
      FILE *file;
    }
    owning_file_output_stream;
    
    static size_t owning_file_output_stream_write(output_stream *stream, char const *data, size_t size)
    {
      owning_file_output_stream *file_stream = (owning_file_output_stream *)stream;
      return fwrite(data, size, 1, file_stream->file);
    }
    
    static void owning_file_output_stream_destroy(output_stream *stream)
    {
      owning_file_output_stream *file_stream = (owning_file_output_stream *)stream;
      fclose(file_stream->file);
    }
    
    /*die konkrete vtable für die abgeleitete Klasse*/
    static output_stream_vtable const owning_file_output_stream_virtuals =
    {
      owning_file_output_stream_write,
      owning_file_output_stream_destroy
    };
    
    /*der Konstruktor*/
    static void owning_file_output_stream_create(owning_file_output_stream *stream, FILE *owned_file)
    {
      stream->base.virtuals = &owning_file_output_stream_virtuals;
      stream->file = owned_file;
    }
    
    static void print_hello(output_stream *out)
    {
      output_stream_write(out, "Hello", 5);
    }
    
    static output_stream *open_hello_stream(void)
    {
      owning_file_output_stream *out;
      FILE *file;
    
      file = fopen("hello.txt", "w");
      if (!file)
      {
        return NULL;
      }
      /*Speicher muss hier dynamisch angefordert werden, damit wir das konkrete Objekt über die Schnittstelle zurückgeben können.*/
      out = malloc(sizeof(*out));
      if (!out)
      {
        fclose(file);
        return NULL;
      }
      owning_file_output_stream_create(out, file);
      return (output_stream *)out;
    }
    
    int main()
    {
      output_stream *out = open_hello_stream();
      if (!out)
      {
        return 1;
      }
      print_hello(out);
      output_stream_destroy(out);
      free(out);
      return 0;
    }
    

    Man kann in C das von Hand machen, was jeder C++-Compiler einem abnimmt.
    In der Praxis macht man das auch so in C. Guter C-Code wie Linux hat vtables ohne Ende.
    FILE aus der C-Standardbibliothek ist übrigens auch lupenreine OOP. Man kann die Schnittstelle mit Standardmitteln nur nicht implementieren.



  • @TyRoXx
    Danke für das Beispiel. Ich habe mir es mal angesehen und mir ist klar warum das OOP ist. Allerdings bin ich wie gesagt nicht mehr ganz fitt in C (hab nur noch mit Java zu tun). Die Funktionen aus deinem bsp. sind aber nicht zugriffssicher, oder?

    @Xin
    Ich möchte wirklich nicht einfach sagen das du falsch liegst.
    Und ich gestehe, dass du dir viel mühe gibst es mir zu erklären.
    Aber irgendwie steige ich bei der Art von Beschreibung nicht durch.
    Für mich hört es sich an als würdest du da was verwechseln. Bzw ich weiß nicht mal wirklich was du da versuchst zu erklären.



  • Sqwan schrieb:

    @TyRoXx
    Danke für das Beispiel. Ich habe mir es mal angesehen und mir ist klar warum das OOP ist. Allerdings bin ich wie gesagt nicht mehr ganz fitt in C (hab nur noch mit Java zu tun). Die Funktionen aus deinem bsp. sind aber nicht zugriffssicher, oder?

    In seiner Implementierung nicht, aber es ist recht einfach nur opaque Zeigern anzubieten. Auf die Member von FILE* kannst du zum Beispiel nicht zugreifen. Zugriffsschutz braucht es mMn aber auch nicht für OOP.



  • cccccccc schrieb:

    Sqwan schrieb:

    @TyRoXx
    Danke für das Beispiel. Ich habe mir es mal angesehen und mir ist klar warum das OOP ist. Allerdings bin ich wie gesagt nicht mehr ganz fitt in C (hab nur noch mit Java zu tun). Die Funktionen aus deinem bsp. sind aber nicht zugriffssicher, oder?

    In seiner Implementierung nicht, aber es ist recht einfach nur opaque Zeigern anzubieten.

    Richtig, man könnte das auch so machen:

    /*nur die Deklaration der Schnittstelle ist im Header, nicht aber die Definition*/
    struct output_stream;
    typedef struct output_stream output_stream;
    
    /*der Benutzer kommt nicht mehr an die vtable heran, also muss er zwangsläufig diese Methode verwenden:*/
    size_t output_stream_write(output_stream *stream, char const *data, size_t size);
    
    /*der Konstruktor fordert dynamisch Speicher an und initialisiert das konkrete Objekt, ohne dass der Benutzer dessen Layout zu Gesicht bekommt*/
    output_stream *owning_file_output_stream_new(FILE *);
    
    /*diese Funktion ruft destroy auf und gibt dann den Speicher frei*/
    void output_stream_delete(output_stream *);
    

    Das macht man nicht unbedingt zum Verstecken der Member, sondern auch für Binärkompatibilität zwischen verschiedenen Bibliotheksversionen. Wenn die konkreten Layouts der Klassen nicht im Header auftauchen, kann man die als Bibliotheksautor bedenkenlos ändern. Die dynamische Bibliothek wird beim Update ausgetauscht und die Anwendungen, die diese verwenden, müssen nicht neu übersetzt werden.

    Nachteile sind die Indirektion und die dynamische Speicheranforderung.



  • Xin schrieb:

    Klassenorientierte(!) Programmierung ist keine Magie in C++, es ist nur eine etwas andere Schreibweise. Hier ist weiterhin alles statisch gebunden.

    Du darft es auch Objektorientierte Programmierung nennen.
    Ich verstehe Deine Absicht hinter dem neuerfundenen Begriff.
    Aber wenn Du begreifst, daß Du OO aus Programmierersicht und nicht aus Sprachsicht sehen sollst, zerfällt sie in warme Luft.



  • volkard schrieb:

    Xin schrieb:

    Klassenorientierte(!) Programmierung ist keine Magie in C++, es ist nur eine etwas andere Schreibweise. Hier ist weiterhin alles statisch gebunden.

    Du darft es auch Objektorientierte Programmierung nennen.
    Ich verstehe Deine Absicht hinter dem neuerfundenen Begriff.
    Aber wenn Du begreifst, daß Du OO aus Programmierersicht und nicht aus Sprachsicht sehen sollst, zerfällt sie in warme Luft.

    Weshalb?


Anmelden zum Antworten