Simple Frage zu Klassen

  • Die Entwicklung von Objective-C und C++ geschah in etwa parallel. Allerdings basiert C++ auf Simula aus den späten 60ern (Ich glaube Simula-67), während Objective-C Smalltalk-80 zugruned liegt.

    Das sind dann konzeptionell 13 Jahre. Witzig an der Geschichte ist übrigens, dass zu Zeiten von Simula der Begriff OOP noch gar nicht bekannt war. Der stammt nämlich von Alan Kay, der erst 1969 mit 29 Jahren sein Examen machte (so etwas wie ein 3D-OO-Modell) und erst ab 1970 zu Xerox wechselte um dort Smalltalk zu entwickeln. Mit anderen Worten: Als die Konzepte für Simula-67 und damit auch für C++ entworfen wurden, gab es OOP begrifflich noch gar nicht.

    Nun mag man meinen, dass die Simula-Jungs Dahl und Nygaard irgndwie schon etwas geschaffen hatten, von dem sie gar nicht wusstern, dass es OOP ist und woraus später C++ wurde. Kay sieht das anders:
    „I invented the term Object-Oriented, and I can tell you I did not have C++ in mind.“

    Deshalb sage ich ja auch immer, dass C++ gar nicht OOP sei, sonder COP (klassen-orientiert, nicht objekt-orientiert. Soweit ich sehe, gibt es in C++ auch gar kein Sprachmittel, das sich auf Objekte bezieht. Ursprünglich hieß übrigens C++ auch C with classes und nicht C with objects.

    Diese Marketingleistung, dass alle welt C++ für OOP hält, lässt einen Stoßtrupp Respekt zollen.

    Damit habe ich dann gleich auch meine Signatur erklärt. ;)

    +++

    Aus der mangelnen OO von C++ erklären sich übrigens auch die Beschränkungen von C++:

    a) C++ kennt eigentlich keine Methoden. Es kennt eigentlich nicht einmal Objekte. Es ist kein Zufall, dass C++ von member functions spricht, alle anderen von Methoden. Ein "Methodenaufruf" in C++ ist nämlich nichts anderes als:

    Quellcode

    1. myObject->doSomething();
    2. // entspricht
    3. myObject->vtab[12]();
    Oder anders formuliert: C++ erzeugt gar keinen Code für Dispatching. Tatschlich habe ich für ein Softwareprojekt so etwas in C gemacht ohne damals etwas von C++ zu wissen.
    Das ist srtukturell nichts anderes als plain C.

    b) Klassen sind daher auch einfache Strukturen, um eine vtab erweitert. Instanzen sind Instanzen dieser Strukturen. Das ist strukturell nichts anderes als plain C.

    c) Dementsprechend kann es in C++ keinen typen id geben.

    d) Das Wichtigste: Es gibt dementsprechend keine Nachrichten in C++. Gar nicht. Überhaupt nicht. OOP ist aber gerade das Versenden von Nachrichten an Objekte.

    +++

    BTW: Das Verhältnis von Smalltalk (ohne es zu kennen) zu Objective-C ist eindeutig so, dass Smalltalk mächtiger ist, insbesondere Blöcke kennt. Erst letztens habe ich einen guten Artikel dazu gelesen, dass der Grundgedanke von Objective-* war, Smalltalk um Eigenschaften zu berauben, um für den Preis der Mächtigkeit und Flexibilität einfachere Compiler zu bauen und vor allem Objective-* übrehaupt compilierbar zu machen. In Zeiten von JIT-Compiling sollte man sich allerdings mal wieder Smalltalk anschauen.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von below
    Ganz richtig. Aber wie ich schon sagte, ich kann mir vorstellen (und Tom ist da überzeugt), dass Objective-C unabhängig von diesen Veränderungen ist.

    So, mein erster Versuch
    Demo.h

    Quellcode

    1. ...
    2. extern size_t n, m;
    3. void fvla(int C[m][n]);
    4. void gvla(int(*)[m][n]);
    5. @interface Demo : NSObject {
    6. ...
    7. }
    8. -(void)testMethod:(int(*)[m][n])vla // sollte ja funktionieren, es ist ein POD der da übergeben wird
    9. -(void)testMethod:(int[]); // das macht er auch
    10. ...
    Alles anzeigen

    fvla und gvla werden tadellos übernommen und auch übersetzt. Dagegen mag er testMethod:(int(*)[m][n]) überhaupt nicht. Scheinbar wird das ganze so umgesetzt, daß das keinen normalen Funktionsaufruf ergibt. Nur ist ehrlich gesagt nicht einzusehen, warum er keine Zeiger auf VLAs als Methodenparametern akzeptiert, wenn dies in einer Funktion möglich ist. Es hängt wohl damit zusammen, daß man VLAs nicht mit File scope deklarieren kann, sondern diese unbedingt in einer Funktion deklariert werden müssen.
  • Also, Vla kannte ich bisher nur als niederländischen Trinkpudding. ;) Virtual logic array?

    Davon unabhängig prüfst du aber gerade den Compiler, nicht die Sprachdefinition.

    BTW: Ist die Klammerung des *-Operators so gemeint?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Tom9811
    Die Entwicklung von Objective-C und C++ geschah in etwa parallel. Allerdings basiert C++ auf Simula aus den späten 60ern (Ich glaube Simula-67), während Objective-C Smalltalk-80 zugruned liegt.

    Das sind dann konzeptionell 13 Jahre. Witzig an der Geschichte ist übrigens, dass zu Zeiten von Simula der Begriff OOP noch gar nicht bekannt war. Der stammt nämlich von Alan Kay, der erst 1969 mit 29 Jahren sein Examen machte (so etwas wie ein 3D-OO-Modell) und erst ab 1970 zu Xerox wechselte um dort Smalltalk zu entwickeln. Mit anderen Worten: Als die Konzepte für Simula-67 und damit auch für C++ entworfen wurden, gab es OOP begrifflich noch gar nicht.

    Wenn man konzeptionell Smalltalk mit einbezieht, reduziert sich die Zeitspanne dann doch auf nur noch 3 Jahre.

    Wichtiger erscheint mir aber die genuine Leistung von Cox und Stepstone insgesamt, nämlich die Idee, die Syntax und Struktur von Smalltalk mit C zu kombinieren. Die Lösung ist absolut pragmatisch und technisch gesehen einfach, nämlich ein Precompiler, der "[object message]" in "objc_msgSend(id self, SEL message, id object...)" (oder so ähnlich) verwandelt und dann irgendeinem C-Compiler zum Fressen gibt. Das alles mit nur einer Handvoll syntaktischer Erweiterungen und Schlüsselwörtern.
    Die Schwierigkeiten gibt es dann mit C, und welchem Compiler.
    I would be embarrassed if they did not spy on me.
  • VLA = variable length array (wird überall in der C Norm so genannt)

    Der Compiler ist leider die Sprachdefinition, sonst hätte ich ja nicht nach einer formalen Definition von Objective-C gefragt.

    Ja, die Klammerung ist bei VLAs so richtig, auch wenn es da einem die Fußnägel hochrollt.
  • zu a) *BOING* Jetzt darf ich den Rest meines Lebens mit dem Abdruck von fünf Fingern auf meiner Stirn herumlaufen. DANKE!

    b) Neee, was ich meine: Objective-C sagt dazu gar nichts. Du kannst da Irgendwas-C verwenden. Natürlich beherrscht der Compiler nicht alle C-Dialekte. IRC gibt es gar keine Compiler, der dsa kann, also auch keinen Plain-C-Compiler. Oder?

    Dementsprechend kann es keinen Objective-C-Compiler geben. C wird ja "mitbenutzt".

    c) müsste es nicht (int*)[n][m] heißen? Ach, was hasse ich das. Egomane Programmierer-Quälerei.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Wenn man konzeptionell Smalltalk mit einbezieht, reduziert sich die Zeitspanne dann doch auf nur noch 3 Jahre.

    ? Simula-67 war 1967 fertig. Smalltalk-80 war 1980 fertig. 1980 - 1967 = 13.

    Die haben ja nicht von 1970 bis 1980 herumgesessen, genau so wenig wie die Simula-Leute von 1960 bis 1967.

    Wichtiger erscheint mir aber die genuine Leistung von Cox und Stepstone insgesamt, nämlich die Idee, die Syntax und Struktur von Smalltalk mit C zu kombinieren. Die Lösung ist absolut pragmatisch und technisch gesehen einfach, nämlich ein Precompiler, der "[object message]" in "objs_msgSend(id self, SEL message, id object...)" (oder so ähnlich) verwandelt und dann irgendeinem C-Compiler zum Fressen gibt. Das alles mit nur einer Handvoll syntaktischer Erweiterungen und Schlüsselwörtern.

    Das ist es eben nicht, weil objc_msg_send() existieren muss. Das ist Code, nämlich das Laufzeit-Dispatching. Du brauchst also eine Übersetzung nach C und ein Laufzeitsystem.

    Bei C++ verhält es sich indessen so, dass man die "OO" tatsächlich komplett in den Compiler legen kann.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Tom9811
    Die Entwicklung von Objective-C und C++ geschah in etwa parallel. Allerdings basiert C++ auf Simula aus den späten 60ern (Ich glaube Simula-67), während Objective-C Smalltalk-80 zugruned liegt.

    Wobei Smalltalk wiederum Anleihen bei Simula macht.

    Nun mag man meinen, dass die Simula-Jungs Dahl und Nygaard irgndwie schon etwas geschaffen hatten, von dem sie gar nicht wusstern, dass es OOP ist und woraus später C++ wurde. Kay sieht das anders:
    „I invented the term Object-Oriented, and I can tell you I did not have C++ in mind.“

    Naja, Kay hat eine sehr eigene Sicht der Dinge. Man muß dieser nicht folgen. Zum Beispiel hat Objective-C die übliche Schmalspurmehrfachvererbung (Interfaces, Protokolle der Name ist eigentlich egal das Konzept ist das gleiche), die Kay für überflüssig hält. Technisch notwendig ist sie in Objective-C genauso wenig wie in SmallTalk. Nur ist das so, daß man Fehler schneller findet, wenn man das Typsystem ausbaut und benutzt und nicht alles zur Laufzeit auflaufen läßt.

    Es prallt hier vorallem eine andere Philosophie von Programmierung aufeinander: strenge Typisierung gegen schwache bzw. gar keine Typisierung. SmallTalk markiert das eine Ende mit extrem schwacher Typisierung und SPARK das andere Ende mit starker Typisierung. Tcl kennt gleich gar keine Typen mehr, alles ist ein String.


    Soweit ich sehe, gibt es in C++ auch gar kein Sprachmittel, das sich auf Objekte bezieht. Ursprünglich hieß übrigens C++ auch C with classes und nicht C with objects.

    Seit der Einführung von RTTI in C++ wäre ich mit solchen Aussagen vorsichtiger.

    Diese Marketingleistung, dass alle welt C++ für OOP hält, lässt einen Stoßtrupp Respekt zollen.

    Das stammt nicht von Stroustrup, er vermeidet Kommentare über andere Sprachen wo es nur geht. Microsoft & Co. dürften einen größeren Anteil daran haben.

    a) C++ kennt eigentlich keine Methoden. Es kennt eigentlich nicht einmal Objekte. Es ist kein Zufall, dass C++ von member functions spricht, alle anderen von Methoden. Ein "Methodenaufruf" in C++ ist nämlich nichts anderes als:

    Quellcode

    1. myObject->doSomething();
    2. // entspricht
    3. myObject->vtab[12]();


    Das ist die häufigste Implementation von statischem Dispatching in C++-Compilern, was nicht heißt, daß dem immer so sein müßte. Das Dispatching muß nur statisch erfolgen, die Implementation ist frei, und es gibt auch andere.


    Das ist strukturell nichts anderes als plain C.

    Message Sending ala Objective-C ist ja auch nichts anderes als ein Funktionsaufruf
    objekt->sendMessage(TypeDesc* objekt, char* name, char** parameterNamen, TypeDesc** parameterTypen, ...) mit dem anschliessendem (Nicht-)Dispatching von name auf eine existierende member function von objekt.

    Es ist daher auch trivial, wenn auch viel Arbeit wegen der komplexen Syntax von C bzw. C++, einen Präcompiler für C++ zu schreiben, der mit reinem C++ (also ohne Rückgriff auf C) dynamisches Dispatching für eine Klassenbibliothek implementiert.

    c) Dementsprechend kann es in C++ keinen typen id geben.

    id ist nichts anderes als ein Basiszeiger auf eine Objekthierachie und die ist auch in C++ möglich. Unterschiede gibt es, wenn man dynamisches Dispatching braucht und nicht mehr mit statischem Dispatching auskommt. C++ erfordert Handarbeit oder einen Präprozessor, in Objective-C ist das nicht notwendig. Verschwiegen werden sollte aber auch nicht, daß das dynamische Dispatching sch*** lahm ist und die Objective-C Laufzeitumgebung nichts tut, dieses Problem aktiv anzugehen, da darf man von Hand nachhelfen. Was aber wiederum mit der schwachen Typisierung zusammenhängt.
  • Original von Tom9811
    IRC gibt es gar keine Compiler, der das kann, also auch keinen Plain-C-Compiler. Oder?

    Die C-Funktionsprototypen frißt der Objective-C Compiler anstandslos, wenn man den C Compiler auf ISO C99 stellt, nur mit der Methodendeklaration hat er seine Probleme.

    c) müsste es nicht (int*)[n][m] heißen? Ach, was hasse ich das. Egomane Programmierer-Quälerei.

    Nein, die ISO Norm definiert das wie vorher beschrieben.
    Ergänzung
    Das geht schon aus einem trivialen Grund nicht. Denk mal an die C-Prototypen

    Quellcode

    1. extern int m,n;
    2. void fvla (int (*r)[m][n]);
    3. // und jetzt schreibe das mal zu
    4. void fvla((int*) r[m][n])
    5. // um
  • Original von Tom9811
    Bei C++ verhält es sich indessen so, dass man die "OO" tatsächlich komplett in den Compiler legen kann.

    Das ist Geschichte, mittlerweile erfordert auch C++ ein Laufzeitsystem. Und dynamic_cast sollte man tunlichst nicht ohne aktives RTTI benutzen wollen. Vor einigen Jahren konnte man noch das RTTI von ettlichen C++-Compilern deaktivieren, weil es in der Anfangsphase einige Probleme gab. Aber das war einmal.
  • a)
    Klar macht Smalltalk Anleihen bei Simula. Es ist ja auch eine Fortentwicklung. Darauf wollte ich hinaus.

    b) Typisierung und Mehrfachvererbung.
    Ja, ich habe schon nicht zu deinemBeitrag oben hinsichtlich der Templates geantwortet. Das würde eine längere Diskussion. ;)

    Tatsächlich wird aber "echte" Merhfachverarbung (Interfaces pp. halte ich für gar keine Mehrfachverarbung, aber noch eine andere Baustelle) znehmend als Designfehler begriffen. Oder sehe ich das falsch? D kann es IIRC auch nicht mehr. Wie es bei C# aussieht, weiß ich nicht.

    Übrigens ist die Fehleranfälligkeit eine Mär:
    mindview.net/WebLog/log-0025
    artima.com/weblogs/viewpost.jsp?thread=4639

    Und ich frage einfach dich: Wie häufig ist es dir passiert, dass du in etwa einer id-getypten Collection eine Instanz einer KLasse hattest, die dort gar nichts zu suchen hatte, sich also überraschend einschlich?

    Mir ist das noch nie passiert. Dir?

    c) RTTI
    Nein. Die RTTI liefert die Klasseninformationen, keine Objekt-Informationen. Mir ist keine Möglichkeit bekannt, eine Frage an ein Objekt zu stellen, die unabhängig von der Klasse ist. In Objective-C geht das etwa mit respondsToSelector: Hier spielen nämlich Klasse, Vererbungshierarchien usw keine Rolle. Du musst auch die Klasse nicht kennen usw. Aber ich lasse mich gerne belehren.

    Ich habe es gerade noch einmal nachgeschlagen ud siehe da:
    de.wikipedia.org/wiki/RTTI
    "RTTI ermöglicht es, zur Laufzeit den Typ eines Objektes zu ermitteln. Somit kann ein Programm während seiner Ausführung ermitteln, welcher konkreten Klasse ein Objekt angehört, auf das eine bestimmte Referenz zeigt. "
    Nichts da mit Objekt-Informationen.

    Das ist vom Standpunkt ja auch klar. Der Name Simula ist ja kein Zufall, sondern war der Anlass. Dort haben wir aber strikte Vererbungshierarchien. Auch in meinem Fall mit selbst gebauter vtab hatten wir das. Am Ende kamen wir irgendwann zum Schluss, dass es nicht immer so geht und wir implementierten dann die Möglichkeit, zur Laufzeit Abfragen zu erstellen. Alles natürlich ganz rudimentär und nicht von Anfang an durchgeplant.

    d) Stoßtrupp
    Okay, kann ich nichtmehr wirklich nachvollziehen. Allerings erinnere ich mich an KOmmentare von Stoßtrupp, die die "OOP"-Eigenschaften von C++ verteidigen.

    e) Dispatching I
    Klar, mir ging es nicht um Implementationsdetails, sondern darum, dass das strukturell statisch ist und daher so (also alleine durch den Compiler) gemacht werden kann.

    f) Dispatching II
    Der Unterschied liegt darin, dass es keine Möglichkeit gibt, dies bereits zur Übersetzungszeit aufzulösen. Das ist strukturell etwas völlig anderes: Das was C++ macht, lässt sich durch reinen Source-Code-Austausch zur Compilzeit erledigen. Das was Objective-C macht, muss durch den /augeführten/ Code zur Laufzeit erledigt werden.

    Das hat mit C rein gar nichts zu tun: Der Dispatching-Code könnte auch in Ada formuliert sein oder Fortran.

    Dass man am Ende alles sogar in Assembler übersetzen kann, ist klar. Sonst gäbe es keine Compiler. Dennoch würde ich nicht dazu tendieren, zu sagen, dass alles strukturell Assembler sei. ;)

    g) Dispatching III
    Nein, du kannst in C++ id nicht sinnvoll definieren. Es ist nämlich /nicht/ ein Root-Element. In id ist /gar nichts/ definiert. Es dient zur Vorlage (Vererbung) /keiner/ Klasse.

    Der Unterschied findet seine /Ursache/ freilich darin, dass id in C++ völlig sinnfrei wäre,da es kein dynamisches Dispatching kennt. Es wäre aber auch unmöglich: Um eine Nachricht^W Funktion aufzurufen, müsste der C-Compiler die vtab kennen. Die kann er aber nicht kennen. Wie auch? In einer Klasse kann doSomething() auf #3 mappen, in einer anderen das gleiche doSomething() auf #7. Ein Aufruf an ein id-Objekt ist also in C++ gar nicht denkbar.

    Eine Lösung wäre es, alle diese Funktionen in eine vtab von id zu stecken und dann wiederum id auf alle vorhandenen Klassen merhfach zu vererben. Das könnte noch einigermaßen funktionieren.

    Aber grundsätzlich würde sich id in C++ wie ein void* verhalten: Da ist was, man kann damit aber nichts anfangen.

    In Objective-C kann ich damit etwas anfangen.

    h) Laufzeitverhalten
    Die Statistiken, die ich kenne, gehen von 1,5-facher bis 2-facher Aufrufzeit einer Objective-C-Methode im Vergleich zu einer C-Funktion (Nicht: C++-Memberfunktion!) aus. Woher hast du deine Daten?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Die C-Funktionsprototypen frißt der Objective-C Compiler anstandslos, wenn man den C Compiler auf ISO C99 stellt, nur mit der Methodendeklaration hat er seine Probleme.

    Argh, BOING II, das hat mit C ja gar nichts mehr zu tun.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Ja, stimmt, mit dynamic_cast ist eine Erweiterung eingetreten. Hatte ich nicht dran gedacht.

    Aber auch diese bezieht sich auf Klassen, nicht auf Objekte. Kennst du wiederum die Klasse nicht, kannst du wiederum damit nichts anfangen.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Tom9811
    b) Typisierung und Mehrfachvererbung.
    ...

    Tatsächlich wird aber "echte" Merhfachverarbung (Interfaces pp. halte ich für gar keine Mehrfachverarbung, aber noch eine andere Baustelle) zunehmend als Designfehler begriffen. Oder sehe ich das falsch?

    Was ist denn ein Protokoll anderes als das Erben von einer rein abstrakten Basisklassen, die nur member functions kennt? Das Protokoll erzwingt, daß die implementierende Klasse, die die von der abstrakten Basisklasse erbt, alle Methoden implementiert.

    Einfache Vererbung mit Protokollen
    Klasse B:
    Implementiert Protokoll A und erbt von Klasse A.

    Mehrfachvererbung
    Klasse B:
    erbt von Klasse A und PA (PA, definiert nur Protokoll A)

    Selbst wenn man nur Protokolle hat, kann es schon zu Konflikten kommen, sollte ich mir mal anschauen wie das in Objective-C aufgelöst wird. Sprachen mit Mehrfachvererbung liefern Mechnismen dieses Problem aufzulösen.

    Das mit dem angeblichem Designfehler war schon immer so. Das ist meist nichts anderes als Dogmatismus. Bei SmallTalk kann man diese Haltung ja noch nachvollziehen, da man es dort nicht wirklich braucht. Aber Oberon-2 und ähnliche Sprachen haben's auch nicht und es bereitet da viel Ärger. Der Aufwand, der in C++ betrieben wird, ist eher gering und fällt meines Erachtens nicht ins Gewicht. Früher wurde Mehrfachvererbung vorallem deshalb verteufelt, weil es angeblich die Performance während der Laufzeit verschlechtern würde. Konflikte bei Mehrfachvererbung sind selten und dafür auf einen einfachen Ansatz für Problemlösungen verzichten?

    Übrigens ist die Fehleranfälligkeit eine Mär:
    mindview.net/WebLog/log-0025

    Mr. Eckel sollte man die Dokumentation zu SPARK durchlesen. Unit Testing ist dort überflüssig. Wenn's compiliert, dann entspricht es der Spezifikation. Man muß die Test erstmal alle schreiben und sinnvoll mit Code befüllen.


    Mir ist das noch nie passiert. Dir?

    Man braucht nur die "richtigen" Kollegen. :( Es gibt Spezies, die SQLs NULL mit einem Magic Key nachbilden, weil das Abfragen von NULL in PHP ja so umständlich sei - hmpf. Daher bin ich pessimistisch.


    f) Dispatching II
    ...
    Das was Objective-C macht, muss durch den /augeführten/ Code zur Laufzeit erledigt werden.

    Ich bin so provokant: 95-99% der Messages die geschickt werden, könnte man so optimieren, daß schon beim Linken des Programms beim Programmstart das aufgelöst wird. Man braucht dann während der Laufzeit nur noch Type-Checks.

    g) Dispatching III
    Nein, du kannst in C++ id nicht sinnvoll definieren. Es ist nämlich /nicht/ ein Root-Element. In id ist /gar nichts/ definiert. Es dient zur Vorlage (Vererbung) /keiner/ Klasse.

    id ist ein Zeiger auf eine implizite Basisklasse (die natürlich nirgends auftaucht und in der Klassenhierachie nicht zu sehen ist), und id versteht das Verschicken von Messages. Bei Gelegenheit werde ich mal an meine C++-Beispielcode weiterschreiben. Ich seh's schon, wenn das so weitergeht, muß ich doch noch als Demogründen einen C++-Präcompiler schreiben.
  • Bei Protokollen beerbt die Subklasse keine Implementierung der "Basisklasse". Instanzvariablen beerbt die Subklasse ohnehin nicht, nicht einmal die Deklaration hierfür. Es ist daher etwas ganz anderes.

    Man kann das in C++ mit Mehrfachvererbung von pvC ohne Membervariablen nachbilden. Das ist dann endgültig von hinten durch die Brust ins Auge.

    ---

    Klar gibt es immer Dinge, die als Designfehler erkannt werden. Es gibt welche, über die man sich sicher streiten kann. Von Mehrfachvererbung kommt man indessen breitflächig weg, wenn ich das richtig sehe. Das hat einen Grund.

    ---

    Die Frage war nicht, ob du pessimistisch bist. Sie war, ob es dir mal passiert ist. Mir noch nicht.

    ---

    Ich weiß nicht, wie provokant du sein willst. Wie sollen aber nur die armen Programmierer in Cupertino wissen, wie die Klasse heißt, die die Action implementiert? Und KVC, KVO, Bindings? Ah, Delegates! Ich glaube, in meinen Applikationen mach das mehr als 1 % bis 5 % aus.

    Es gibt einen Grund dafür, dass es das in C++ nicht gibt. Das ist kein Zufall.

    ---

    Nein, id ist kein Zeiger auf eine Basisklasse, die nicht implementiert ist. Das sieht man schon daran, dass id alle Methoden kennt. Wenn es eine Basisklasse wäre, dann müssten alle Subklassen (also alle Klassen im Programm schlechthin) alle Methoden kennen, was a) nicht so ist und b) völlig unsinnig wäre.

    id ist einfach keine Klasse. Es entspricht void*. Mit void* kann man nichts anfangen, mit id schon.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Tom9811
    Bei Protokollen beerbt die Subklasse keine Implementierung der "Basisklasse". Instanzvariablen beerbt die Subklasse ohnehin nicht, nicht einmal die Deklaration hierfür. Es ist daher etwas ganz anderes.

    Du hast eine sehr eingeengte Sicht der Dinge.

    Man kann das in C++ mit Mehrfachvererbung von pvC ohne Membervariablen nachbilden. Das ist dann endgültig von hinten durch die Brust ins Auge.

    Die Lösung von C++ ist flexibler, sie erlaubt es Referensimplementationen den Protokollen mitzugeben und man kann auch Variablen vererben. Das Wichtige sind die Methoden und nicht die Variablen, den die sollten sowie so gekapselt sein.

    Klar gibt es immer Dinge, die als Designfehler erkannt werden. Es gibt welche, über die man sich sicher streiten kann. Von Mehrfachvererbung kommt man indessen breitflächig weg, wenn ich das richtig sehe.

    Da habe ich meine Zweifel, mal eine kleine Aufstellung von häufig verwendeten Programmiersprachen
    Mehrfachvererbung
    C++, CLOS, Eiffel, Python
    Mehrfachvererbung durch Interfaces/Protokolle
    Ada95, Java, Objective-C, PHP5, Ruby
    Einfachvererbung
    Smalltalk(?), PHP4

    Bei Perl muß ich passen, und C# gehört wahrscheinlich in den Bereich Java & Co.

    Man kann natürlich sagen, daß eine echte OO-Programmiersprache nicht nur dynamisches Dispatching sondern auch mutiple Dispatching beherrschen muß. Aber dann wird die Liste recht kurz. Nur CLOS erfüllt das.

    Sie war, ob es dir mal passiert ist.

    Ja

    Ich weiß nicht, wie provokant du sein willst. Wie sollen aber nur die armen Programmierer in Cupertino wissen, wie die Klasse heißt, die die Action implementiert?

    Bitte etwas mehr Phantasie Tom. Was machst Du fast immer beim Programmieren in Objective-C?
    Du schickst Message, deren Prototyp statisch ist, im Sinne der Name der Funktion und die Namen der Parameter sind zum Compilzeitpunkt bekannt. Ferner erwartest Du von dem Objekt, daß es sich wie ein bestimmer Typ verhält (ob man nun zwischen Mehrfachvererbung oder Einfachvererbung und Protokolle unterscheidet ist Kinderkram es ändert nichts fundamental an der Sache), oder aber von einem anderem Typ ist und mit der Nachricht nichts anfangen kann.

    Wann kann man neue Methoden definieren und implementieren? In Objective-C jedenfalls nicht während der Laufzeit, man kann nur compilierte Objekte während der Laufzeit nachladen, dazu wird die Eigenschaft des OS benutzt die sich Runtime Linker nennt. Im Falle von MacOS X ist der dyld gemeint. Es gibt also ein exakt definierten Zeitpunkt an dem neue Methoden in das Programm eingeführt werden, der Zeitpunkt des dynamischen Bindens der ausführbaren Objektmodule.

    ...
    Der Rest demnächst
  • Du hast eine sehr eingeengte Sicht der Dinge.

    *

    Die Lösung von C++ ist flexibler, sie erlaubt es Referensimplementationen den Protokollen mitzugeben und man kann auch Variablen vererben. Das Wichtige sind die Methoden und nicht die Variablen, den die sollten sowie so gekapselt sein.

    Nein, C++ relaubt keine Protokolle, sojndern nur die Vererbung. Dadurch, dass du einfach sagstm, es sei ja alles dasgleiche und dann noch die Unterschiede aufzählst, ändert sich das ja nicht.

    Bei einer Vererbung (Zuletzt war es doch eine Vererbung?) sind übrigens die Instanzvariablen regelmäßig nicht gekapselt. Insofern verstehe ich dieses Argument nicht.

    Mehrfachvererbung durch Interfaces/Protokolle
    Ada95, Java, Objective-C, PHP5, Ruby

    Ja, wenn du alles in einen Topf wirfst, findet du mehr. Dann gibt es indessen auch keinen Unterschied mehr. Bemerkenswert ist indessen, dass alle Welt von den Programmiersprachen, die Protokolle, Interfaces (oder wie die Bezeichnung auch immer gerade ist) sagt, dass sie keine Mehrfachvererbung untestützen.

    Ja

    Das hätte ich gerne konkreter. Wir haben nämlich beim vorletzten Treffen eine Umfrage gemacht und niemand sagte "Ja".

    Bitte etwas mehr Phantasie Tom.

    *

    Du schickst Message, deren Prototyp statisch ist, im Sinne der Name der Funktion und die Namen der Parameter sind zum Compilzeitpunkt bekannt.

    Nein, bereits beim primitivsten Action-Target-Paradigma, welches schon 10.0 implementierte, ist der Name zur Übersetzungszeit nicht bekannt.

    Ferner erwartest Du von dem Objekt, daß es sich wie ein bestimmer Typ verhält (ob man nun zwischen Mehrfachvererbung oder Einfachvererbung und Protokolle unterscheidet ist Kinderkram es ändert nichts fundamental an der Sache), oder aber von einem anderem Typ ist und mit der Nachricht nichts anfangen kann.


    Erneut nein. Ich frage ab, ob eine bestimmte Methode, die ich aus einer Datei zur Laufzeit geladen habe (oder die zur Laufzeit gesetzt wurde), vorhanden ist.

    Wann kann man neue Methoden definieren und implementieren? In Objective-C jedenfalls nicht während der Laufzeit, man kann nur compilierte Objekte während der Laufzeit nachladen, dazu wird die Eigenschaft des OS benutzt die sich Runtime Linker nennt

    Man kann Methoden nach der Übersetzungszeit des Aufrufers implementieren, also die Methodenaufrufe erst lange nachdem ich den Button in Cupertino programmiert habe, durch Lesen eines Nibs ermitteln.

    * Danke für die Diskussion.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?