Performancemythen?
-
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?
-
Xin schrieb:
Tim schrieb:
Was haben wir hier eigentlich. Wir haben zwei Parteien: Die eine hat eine schwammige, unpräzise Definition von OOP, die andere eine harte, präzise. Was mich dabei aber wundert ist, dass in einem Forum mit den übelsten Pedanten, ANSI-Standard-Fetischisten und undefined-behaviour-Propheten eben die unexakte, schwammige Definition besser angenommen wird.
In dem Fall bin ich wohl der Pedant ^^
Das ist okay, denn es stimmt hier ja. Ich möchte nur nebenher erwähnen, dass zwar scharfe gezogene Definitionen schätze, aber deswegen nicht grundsätzlich pedantisch bin.
Hier bin ich Pedant, solange niemand die Frage auf Seite 11 sinnvoll beantwortet oder es wenigstens versucht.Es gibt zahlreiche andere Definitionen hier in dem Thread, die ebenfalls "scharf" sind. Deine ist einfach nur Falsch in der Hinsicht, dass die Mehrheit der Programmierer sie wohl einfach nicht teilt. Aber wie ich schon sagte: Du kannst meinetwegen auch Blau zu Grün sagen...
-
rüdiger schrieb:
Komisch finde ich nur, dass der Graham Artikel hier vieles voraus gesehen hat...
Der ist nicht von Graham!
Der ist von Rees!
(Wir reden schon von http://www.paulgraham.com/reesoo.html, oder?)
-
Xin schrieb:
class Figure { public: virtual void draw() = 0; // pure virtual == abstract } class Triangle : public Figure { public: void draw(); }; class Circle : public Figure { public: void draw(); }; template<typename Shape> void foo(Shape* s) { s->draw(); }
Und damit ist es jetzt auch OOP.
Das ist oop? wieso sollte das denn nach deienr definition oop sein? Du argumentierst doch immer, dass der Compiler diese virtual komponente sehen muss.
Du sagst sogar, dass der compiler, sobald der virtual overhead entfernt wird, aus dem oo code non oo code macht.Circle test; foo(&test);//kein virtueller funktionsaufruf
so schießt du dir selbst ins knie(auch wenn du das oft genug getan hast)
machst du hingegen sowas:
Circle test; foo(static_cast<Figure*>(&test)); //oder Figure* test2=new Circle; foo(test2);
dann hast du templates nicht verstanden. Auch ein beinschuss.
Entweder verstehe ich nicht, was Du unter "Abstrakt" verstehst oder Du kommst in C++ um virtual nicht herum.
wikipedia:
Im mathematischen Sinne bezeichnet Abstraktion einen Prozess, bei dem individuelle, zufällige Einzelheiten weggelassen (abstrahiert) werden, zugunsten des Allgemeinen, Wesentlichen.Es geht bei der Abstraktion nicht um "abstrakte methoden" oder "abstrakte Objekte", sondern zuallererst um den Denkvorgang. Was für Eigenschaften brauch ich? Was ist von ihnen für mein Problem wichtig?
Daraus kristallisiert sich ein interface. Nun kannst du dich entscheiden es als abstrakte basisklasse zu implementieren, oder das interface als Denkonstrukt lassen, und mithilfe von templates einfach nur ein interface durch nutzung der methoden zu definieren.
-
rüdiger schrieb:
Xin schrieb:
rüdiger schrieb:
Xin schrieb:
dv_ schrieb:
Du glaubst allen ernstens, dass OOP nur aus dynamic dispatch besteht? Mann, du hast wirklich eiskalt alle Messlatten vergraben. Lass dir gesagt sein: OOP ist mehr als nur dynamic dispatch.
Ist das alles, was als Begründung kommt?
Wenn Du mir etwas mitteilen möchte, dann stelle nicht nur Behauptungen auf, sondern begründe sie.a.foo();
Nachricht an ein Objekt gesendet => OOP.
Sorry, hier ist es leider schon vorbei.
Das ist Syntax, die Realität sieht auch bei a.foo(); so aus:ClassOfA::foo( a );
Aufruf einer statischen Funktion, mit dem Objekt als erstem Argument.
Wenn a.foo() OOP ist, ohne virtuell zu sein, dann ist printf() ebenfalls OOP.
foo ist eine Nachricht an a. Was der Compiler daraus macht ist egal.
Wie da steht - ohne virtuell zu sein - kann da nicht objektorientiertes draus werden.
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.[/quote]
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.Wenn ClassOfA::foo( ClassOfA * ) OOP, wie behauptet wird, so ist printf ebenfalls OOP in Abhängigkeit des ersten Argumentes.
Was der Compiler daraus mag Dir ja egal sein, aber es equivalent zum Sourcecode. Aus einem statischen Funktionsruf wird ohne Compilerfehler kein OOP mehr.
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.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.
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.
-
Xin schrieb:
printf ist eine statische Funktion. Sie ist nicht OOP.
ClassOfA::foo( ClassOfA * ) ist eine statische Funtion. Sie ist nicht OOP.Wenn ClassOfA::foo( ClassOfA * ) OOP, wie behauptet wird, so ist printf ebenfalls OOP in Abhängigkeit des ersten Argumentes.
Was der Compiler daraus mag Dir ja egal sein, aber es equivalent zum Sourcecode. Aus einem statischen Funktionsruf wird ohne Compilerfehler kein OOP mehr.
Und das ist von A bis Z falsch. Nochmal: ClassOfA::foo ist objektorientiert, WEIL CLASSOFA EINE ZUSAMMENFÜHRUNG VON DATEN UND FUNKTIONALITÄT IST. Und foo IST eine Funktionalität.
Statisch = kein OOP, virtuell = OOP ist auf jeden fall komplett falsch.
-
otze schrieb:
Xin schrieb:
class Figure { public: virtual void draw() = 0; // pure virtual == abstract } class Triangle : public Figure { public: void draw(); }; class Circle : public Figure { public: void draw(); }; template<typename Shape> void foo(Shape* s) { s->draw(); }
Und damit ist es jetzt auch OOP.
Das ist oop? wieso sollte das denn nach deienr definition oop sein? Du argumentierst doch immer, dass der Compiler diese virtual komponente sehen muss.
Hier ist doch alles offensichtlich. Für mich, wie auch für den Compiler.
Zwischen Circle und Figure existiert die gerichtete, die Funktion draw wird objekt orientiert gesetzt.Das Template hat damit nix zu tun. Gibst Du als Typ "Figure" an, kannst Du problemlos und typsicher Circles und Triangles zeichnen. Du hättest auch direkt s->draw() schreiben können, das Template tut schließlich überhaupt nichts.
rüdiger schrieb:
Du sagst sogar, dass der compiler, sobald der virtual overhead entfernt wird, aus dem oo code non oo code macht.
Ich sage, dass es eine (1) Möglichkeit gibt, wo der Compiler OOP entfernen kann. Die Möglichkeit ist genannt (es existiert keine Subklasse der Basisklasse mit virtueller Funktionalität) und die liegt hier nicht vor.
Hier wird kein OOP entfernt.rüdiger schrieb:
Circle test; foo(&test);//kein virtueller funktionsaufruf
so schießt du dir selbst ins knie(auch wenn du das oft genug getan hast)
Der Ruf der Templatefunktion foo ist rein statisch. Statischer Aufruf, kein OOP.
Die Templatefunktion ruft die Funktion Shape::draw. Aufruf über OOP, wenn Shape::draw virtual definiert ist. Das ist z.B. der Fall, wenn Shape == Figure gesetzt wird. Ansonsten wird eine Template-Funktion foo erzeugt, die einen statischen Funktionsruf erzeugt. Dann kein OOP.Meinem Knie geht's wunderbar.
rüdiger schrieb:
machst du hingegen sowas:
Circle test; foo(static_cast<Figure*>(&test)); //oder Figure* test2=new Circle; foo(test2);
dann hast du templates nicht verstanden. Auch ein beinschuss.
Kompiliere es, teste es. Funktioniert doch alles, wie ich beschrieben hbae.
Du kannst kein Objekt vom Typ Figure herstellen. Figure ist ein Interface, aber selbstverständlich darfst Du Figure::draw() aufrufen. Das ist kein statischer Aufruf, sondern genau das ist OOP.
Abhängig vom Objekt (ob Circle oder Triangle) wird mit Hilfe von OOP die Funktion Circle::draw() oder Triangle::draw() aufgerufen.Wenn Beinschuss, dann nicht von mir. Ich arbeite sehr viel mit OOP und auch sehr viel mit Templates.
Ich mache keine Schnellschüsse.
-
printf ist eine statische Funktion. Sie ist nicht OOP.
ClassOfA::foo( ClassOfA * ) ist eine statische Funtion. Sie ist nicht OOP.Wenn ClassOfA::foo( ClassOfA * ) OOP, wie behauptet wird, so ist printf ebenfalls OOP in Abhängigkeit des ersten Argumentes.
Nein, weil eben die bedeutung des sources eben nicht gleich der logischen bedeutung ist. printf ist wenn dann eine methode von stdout, aber dieser wird auch nur benutzt. printf ist keine funktion von string, weil es zwischen "Zeichenkette" und "standardausgabe" keine direkte logische verbindung gibt. Desweiteren hat das erste sprintf argument, der formatstring höchstens aggregationscharacter, er wird benutzt um die anderen argumente richtig formatieren zu können und das ergebnis wird auf stdout ausgegeben.
Im gegensatz dazu steht foo in einer direkten logischen verbindung zu foo, denn als Mitglied von ClassOfA ist es auch auf jeden Fall teil der abstraktion.
-
otze schrieb:
printf ist eine statische Funktion. Sie ist nicht OOP.
ClassOfA::foo( ClassOfA * ) ist eine statische Funtion. Sie ist nicht OOP.Wenn ClassOfA::foo( ClassOfA * ) OOP, wie behauptet wird, so ist printf ebenfalls OOP in Abhängigkeit des ersten Argumentes.
Nein, weil eben die bedeutung des sources eben nicht gleich der logischen bedeutung ist. printf ist wenn dann eine methode von stdout, aber dieser wird auch nur benutzt. printf ist keine funktion von string, weil es zwischen "Zeichenkette" und "standardausgabe" keine direkte logische verbindung gibt. Desweiteren hat das erste sprintf argument, der formatstring höchstens aggregationscharacter, er wird benutzt um die anderen argumente richtig formatieren zu können und das ergebnis wird auf stdout ausgegeben.
Im gegensatz dazu steht foo in einer direkten logischen verbindung zu foo, denn als Mitglied von ClassOfA ist es auch auf jeden Fall teil der abstraktion.
Die Verbindung bei printf zu (const char gibt es, aber sie ist natürlich an den Haaren herbei gezogen.
Dennoch ist diese haarsträubende Verbindung genauso stark wie ClassOfA::foo( ClassOfA * this ): Es ist das erste Argument.Nochmals zur Verdeutlichung: "printf" ist nicht OOP. "ClassOfA::foo" ist in dem Beispiel genauso implementiert, wie "printf". In beiden Fällen wird der Aufruf nicht objektorientiert umgesetzt, sondern statisch.
Eine objektorientierte Verbindung liegt dann vor, wenn von ClassOfA ein Interface für andere Klassen darstellt und die Funktion als virtuell oder abstrakt (virtual ...= 0;) gekennzeichnet wird.
Dann wird erst abhängig vom Objekttyp die passende statische Funktion ausgesucht und anschließend aufgerufen: OOP.
-
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.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.
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.
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.
Ob ich nun ein Interface Shape einführe oder es nur im Geiste habe - ändert die Idee des Codes nicht und ändert faktisch sogar den ASM Code nicht - wenn der Compiler clever ist.
-
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. Normalerweise ist eine Funktion aber Member, weil sie Daten des Objektes verwendet, um gewisse Entscheidungen zu treffen und Operationen durchzuführen. 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?
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.
-
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 dassinterface 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.
Also stellt Xin eine prezisere Definition auf:
"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, und es erst zur Laufzeit entschieden wird, welches einzelne Objekt diese Nachricht bekommt, dann ist es OOP."Also fuer euch ist OOP:
- encapsulation,
- inheritance,
- or polymorphism
Wobei das, mit genuegend Phantasie, sich auf alles anwenden laesst.Fuer Xin ist OOP:
- encapsulation,
- inheritance,
- and polymorphismWenn 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. Normalerweise ist eine Funktion aber Member, weil sie Daten des Objektes verwendet, um gewisse Entscheidungen zu treffen und Operationen durchzuführen. 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?
Und wieder, kein einziges Wort ueber Polymorphismus. Wenn diese Daten also nicht im class-Space sind, sondern irgendwo anders gespeichert werden (z.B. in einer Datenbank), dann wird es nicht mehr OOP?
-
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 dassinterface 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!
scnrNatü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 Javaclass 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.)