Was ist OOP eigentlich?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
olliander
User
Beiträge: 11
Registriert: Samstag 12. Juli 2008, 03:08
Kontaktdaten:

Leonidas hat geschrieben:
olliander hat geschrieben:Nehmen wir als Bsp. eben einen Java-Entwickler, der über den Tellerrand hinaus schauen möchte (wunderbar), und jetzt eben auf Python umsteigt. Er ist nichts anderes gewohnt, als 'seine OOP'. Also wird er versuchen, sie auch in Python einzusetzen... Und diese Möglichkeit ist ihm gegeben. Finde ich an sich gar nicht verkehrt.
Richtig. Dann kann er XML zur Konfiguration verwenden, Seine Attribute mit `__` prefixen und wilde Klassenhierarchien bauen, sowie Getter und Setter implementieren etc. Aber das ist ja wohl kaum sinnvoll. Wenn man eine Sprache wechselt, sollte sich das auch im Denken niederschlagen. Ich schreibe in Scheme auch kein Python und in Java kein C. Man sollte schon idiomatischen Code schreiben, sonst ist ja die Idee eine Sprache zu nehmen die einem Arbeit erspart ad-absurdum geführt indem man sich die Arbeit eben wieder aufhalst, die einem die Sprache eben abnehmen würde.
Sag' das nicht mir... ;)
Ich versuche nur, Alltagsbeispiele reinzubringen. Sprich: Wie sieht es in der Praxis aus. Und nicht: Wie denke ich, dass es in der Praxis aussehen sollte.
olliander hat geschrieben:Und wer heute nach wie vor ohne OOP entwickelt, bspw. prozedural... Wird erstmal schief angeschaut, obwohl prozedurale Programmierung in seinem Falle evtl. durchaus sinnvoll ist. ;)
Von wem? Ich schaue Programme schief an die auf Teufel-komm-raus OOP nutzen, obwohl es Blödsinn ist. Und damit bin ich nicht der einzige. Natürlich schaue ich im Gegensatz auch Programme schief an, die prozedural sind, obwohl OOP dort sehr hilfreich wäre. Dogmatismus Pro-OOP und Kontra-OOP ist beides Quatsch.
Es geht mir hier um die Beleuchtung des allgemeinen OOP-Hype. Wie er auch alltäglich die Runde macht. Mir gehen diese selbsternannten Hüter der OOP schlicht und ergreifend auf den Zeiger, wie Du selbst schon sagtest... Mehr als kontraproduktiv ist das Ganze sicher nicht. Aber es ist nunmal (leider) Fakt, dass dies auftritt.

Also ist es, abseits des allgemein evtl. etwas zu weit reichenden Verständnis- bzw. Interpretationsbereiches von OOP, und abseits der Definitions- und "Halt' dich gefälligst an die entsprechenden Prinzipien!"-Problematik gar nicht so einfach, auf einen gemeinsamen Nenner zu kommen. Deswegen ist es auch schwierig, sich hinzustellen, und zu sagen: Du machst das falsch. Bzw. als Reaktion darauf Akzeptanz zu bekommen. Meiner Meinung nach.

Missverständnisse, Streits, etc...

Nachtrag:
Im Endeffekt legt denke ich jeder selbst fest, wann etwas für ihn Sinn macht, wann OOP aufhört und Schwachsinn anfängt etc... Und das finde ich durchaus interessant. Besonders bezgl. der Ergebnisse, die teilweise dabei heraus kommen. ^^

Liebe Grüße,
olliander
Wadd nich passt, wird passend jemacht.
DeJe
User
Beiträge: 39
Registriert: Sonntag 23. November 2008, 19:38

Ganz ketzerisch?
Für mich ist OOP nur eine andere Semantik! Letzlich ist gutes Design wichtig, das betrifft Daten, Strukturen und Funktionen. Funktionalität und Algorithmen werden durch OOP ja nicht überflüssig oder obsolet. ;)
Durch OOP wird/wurde es möglich Module besser zu kapseln, besseren Überblick zu halten. Aber ganz ehrlich, soooo ein riesen Unterschied zur funktionalen Programmierung stellt es für mich nicht dar.

wo ist der Unterschied zwischen:
foo(bar) und bar.foo() :twisted:
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Beim ersten wird die Funktion foo mit dem Parameter bar aufgerufen. Beim zweiten ist bar eine Instanz und besitzt die Methode foo, d.h. die Methode wird von bar ausgeführt (natürlich nicht wirklich, das macht der Interpreter).
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

DeJe hat geschrieben:Aber ganz ehrlich, soooo ein riesen Unterschied zur funktionalen Programmierung stellt es für mich nicht dar.
Du meinst wohl eher Prozedurale Programmierung. Funktionale Programmierung unterscheidet sich dann doch ein gutes Stück von OOP.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
DeJe
User
Beiträge: 39
Registriert: Sonntag 23. November 2008, 19:38

Jap, prozedurale Programmierung natürlich. @Leonidas. ;)

@derdon. sicher. Aber wo besteht der grundsätzliche Unterschied? Die Funktion führt eine Operation aus. Es spielt keine Rolle ob ein "Objekt" diese Operation anfordert oder diese Funktion mit einem "Objekt" (Datenstruktur) angefordert wird. Das Ergebnis bleibt das gleiche. Das Objekt (die Datenstruktur) wird in der Funktion/Methode behandelt/bearbeitet.
Letztlich ist OOP "nur" ein anderes Modell auf gedanklicher Ebene.
olliander
User
Beiträge: 11
Registriert: Samstag 12. Juli 2008, 03:08
Kontaktdaten:

DeJe hat geschrieben:Ganz ketzerisch?
Für mich ist OOP nur eine andere Semantik! Letzlich ist gutes Design wichtig, das betrifft Daten, Strukturen und Funktionen. Funktionalität und Algorithmen werden durch OOP ja nicht überflüssig oder obsolet. ;)
Durch OOP wird/wurde es möglich Module besser zu kapseln, besseren Überblick zu halten. Aber ganz ehrlich, soooo ein riesen Unterschied zur funktionalen Programmierung stellt es für mich nicht dar.
Irgendwie brachte mich das gerade auf folgenden Gedanken: Es wird verlangt, dass man OOP bevorzugt in Bezug auf Semantik mit 'Sinn' befüllt... Für mich wäre die Umkehrung mittlerweile mal richtig interessant. ^^

Sprich: Ist OOP nicht genauso interessant bzw. nützlich, wenn man sie völlig losgelöst von diversen, ich nenne es einfach mal ketzerisch so, esoterischen Interpretationen verwendet, getreu dem Motto: Klassen sind nichts anderes als Namensräume, Methoden nichts anderes als Funktionen und Attribute nichts anderes als Referenzen?

Gut, das mag etwas simpel gedacht sein, aber irgendwo ist die Frage für mich recht interessant. Und ich hoffe, das Ganze wird nicht falsch verstanden. ^^

Liebe Grüße,
olliander
Wadd nich passt, wird passend jemacht.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

olliander hat geschrieben:Sprich: Ist OOP nicht genauso interessant bzw. nützlich, wenn man sie völlig losgelöst von diversen, ich nenne es einfach mal ketzerisch so, esoterischen Interpretationen verwendet, getreu dem Motto: Klassen sind nichts anderes als Namensräume, Methoden nichts anderes als Funktionen und Attribute nichts anderes als Referenzen?
Nenne Module Klassen und schon bist du Fertig. Denn Module sind ja genau Namensräume mit Namen (Attributen), Funktionen (Methoden) etc. Du kannst sie sogar dynamisch zur Laufzeit erstellen.

DeJe: Das ist genau das was ich in meinem ursprünglichen Posting zum Thema OOP meinte, siehe GTK+. OOP ist nicht mit einer bestimmten Syntax verbunden, das was wir in vielen Sprachen haben ist eben syntaktischer Zucker der es etwas angenehmer macht.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

@DeJe: Der wichtigste Unterschied zwischen ``foo(bar)`` und ``bar.foo()`` ist die Polymorphie beim zweiten Fall. Je nach dem an was `bar` gebunden ist, wird ein anderes `foo()` *automatisch* ausgeführt, wo man beim ersten Fall explizite Fallunterscheidungen in der Funktion `foo()` machen muss, was hässlich und unflexibel ist.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

es sei denn, man nutzt Multimethods, dann hat man polymorphe Funktionen. :D
BlackJack

Okay, dass wäre zumindest in Python dann aber nicht der offensichtliche Weg, den das Zen ja nahelegt. :-)
DeJe
User
Beiträge: 39
Registriert: Sonntag 23. November 2008, 19:38

BlackJack hat geschrieben:@DeJe: Der wichtigste Unterschied zwischen ``foo(bar)`` und ``bar.foo()`` ist die Polymorphie beim zweiten Fall. Je nach dem an was `bar` gebunden ist, wird ein anderes `foo()` *automatisch* ausgeführt, wo man beim ersten Fall explizite Fallunterscheidungen in der Funktion `foo()` machen muss, was hässlich und unflexibel ist.
Ja sicher. Aber der Compiler/Interpreter übernimmt uns die Auswahl der richtigen Funktion implizit. Sie muß ja trotz allem getroffen werden. ;)
Es ist vielleicht hässlich anzusehen, aber unflexibel ist eine explizite Fallunterscheidung in der Funktion nicht. Man kann sich sogar "objektorientierter" Methoden bedienen und die Datenstruktur selbst mit Funktionsreferenzen füllen, die wiederum aufgerufen werden. Das funktioniert sogar in C und voilà, wir haben OOC. :D

Code: Alles auswählen

typedef void (func) (void *d);

typedef struct {
	int	i;
	func *f;
} Daten;

void do_something_a(Daten *d)
{
	d->i++;
}

void do_something_b(Daten *d)
{
	d->i += 10;
}

int do_something(Daten *d)
{
	d->f(d);
	return d->i;
}

int main(int argc, char **argv)
{
	Daten a = { 0, (func*)do_something_a };
	Daten b = { 10, (func*)do_something_b };

	printf( "%d, %d\n", do_something(&a), do_something(&b) );

	a.f(&a);
	b.f(&b);
	printf( "%d, %d\n", a.i, b.i );

	return 0;
}
Wie gesagt, es geht nur darum das OOP mehr ein Gedankenmodell ist als konkret an eine Programmierspache oder Syntax gebunden zu sein. Das "Beispiel" würde natürlich Niemand wirklich so programmieren. Wie Leonidas schon sagte, die Programmiersprachen geben den Zucker dazu, manche besser, manche schlechter. Vererbung und Polymorphie wird implizit von der Programmiersprache erzeugt. Bei einer Sprache die das nicht hat muß der Programmierer eben explizit dafür sorgen.
BlackJack

@DeJe: Doch die Fallunterscheidung in der Funktion wäre unflexibler. Du machst sie in Deinem C-Beispiel ja auch gar nicht, weil Du da OOP verwendest, ohne *explizite* Fallunterscheidung *in der Funktion*. Genau da ist OOP ja schöner, sinnvoller, einfacher. Danke das Du das nochmal gezeigt hast. :-)
DeJe
User
Beiträge: 39
Registriert: Sonntag 23. November 2008, 19:38

BlackJack hat geschrieben:...Danke das Du das nochmal gezeigt hast. :-)
Gern geschehen. :D
Das Beispiel sollte aber nur zeigen das auch in ansonsten nicht-oo Sprachen eine Art objektorientierte Programmierung möglich ist.
BlackJack hat geschrieben: Genau da ist OOP ja schöner, sinnvoller, einfacher.
Ein Beispiel für Fallunterscheidung in einer Funktion spare ich mir mal. ;) Es reicht ein enum (in der Struktur) um den Typ der Daten mitzugeben und ein switch in der Funktion um diesen Typ auszuwerten. Natürlich läßt sich sowas in einer objektorientierten Sprache besser und einfacher realisieren. Aber flexibel ist man bei einer prozeduralen Lösung ebenso.

Aber das ist alles theoretisch. Niemand (ich zumindest nicht) käme auf die Idee OOP mit C oder Pascal zu implementieren. :D
BlackJack

@DeJe: Nochmal: Man ist damit *nicht flexibel*! Dann hat man mehrere Datentypen und mehrere Funktionen wo in jeder ein ``switch`` steckt. Wenn man einen weiteren Typen hinzufügen will, muss man in allen beteiligten Funktionen und ``switch``-Konstrukten Code für den neuen Typen hinzufügen. Mit OOP, auch mit selbstgebastelten in C, kann man einen neuen Typen hinzufügen ohne den alten Code anzufassen und riesige Funktionen zu schreiben, die alle Untertypen behandeln.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

An dieser Stelle möchte ich mal Lauf, Forest, lauf! einwerfen, in dem zweiseitigen Artikel ist recht kurz und prägnant beschrieben wie die Objective C Laufzeitumgebung funktioniert und welchen C Strukturen sie entspricht. Ist imo ein schönes Beispiel wie man OOP in C realisieren kann.
DeJe
User
Beiträge: 39
Registriert: Sonntag 23. November 2008, 19:38

BlackJack hat geschrieben:@DeJe: Nochmal: Man ist damit *nicht flexibel*! Dann hat man mehrere Datentypen und mehrere Funktionen wo in jeder ein ``switch`` steckt. Wenn man einen weiteren Typen hinzufügen will, muss man in allen beteiligten Funktionen und ``switch``-Konstrukten Code für den neuen Typen hinzufügen.
Nicht unbedingt.

Code: Alles auswählen

typedef enum { daten_a, daten_b } DatenTyp;

typedef struct {
	DatenTyp Typ;
	int	i;
} Daten;

void do_something_a(Daten *d)
{
	d->i++;
}

void do_something_b(Daten *d)
{
	d->i += 10;
}

int do_something(Daten *d)
{
	switch(d->Typ) {
	case daten_a:
		do_something_a(d);
		break;
	case daten_b:
		do_something_b(d);
		break;
	default:
		break;
	}
	return d->i;
}

int main(int argc, char **argv)
{
	Daten a = { daten_a, 0 };
	Daten b = { daten_b, 10 };

	printf( "%d, %d\n", do_something(&a), do_something(&b) );

	return 0;
}
Ich muß nur das enum und ein switch erweitern (und natürlich eine neue Funktion do_something_c schreiben) um einen neuen Typ zu kreieren. Anderer Code wird davon nicht beeinflusst.

Aber lassen wir das, wir werden damit langsam offtopic. ;)

PS: Und ganz ehrlich, von diesem Code bekomme selbst ich Augenkrebs. :D
BlackJack

Du zeigst schon wieder das was ich gesagt habe. Du musst immer an zentralen Stellen die ``enum``\s und die ``switch``-Anweisungen erweitern. Und entweder in der Quelltextdatei die neue Funktion implementieren oder zumindest dort den Header ``include``\n wo die Implementierung drin steckt. Die Implementierung eines neuen Typs verteilt sich über das ganze Programm. Im Grunde sagt Du doch auch, Du musst nur "alles" anfassen, der Rest bleibt unverändert. Nur welcher Rest bleibt denn da noch unberührt!?
Konrad Wenzel
User
Beiträge: 15
Registriert: Freitag 3. Oktober 2008, 17:19

@Leonidas: OOP bildet hervorragend die Fantasiewelten mit handelnden Robotern ab, für Modelle aus der realen Welt eignen sich oft andere Ansätze besser, wie sie z.B. in den erfolgreichen Sprachen SAS, SPLV oder Natural sehr unterschiedlich angelegt sind ( es gibt sie mittlerweile nicht nur für IBM-Maschinen).
Von Python schätze ich vor allem die Fähigkeit, ohne Umstände komplexe Zahlen in elektrotechnischen Aufgaben zu verarbeiten und die Möglichkeiten zur Textverarbeitung als ehrenamtlicher Mitarbeiter in einem Aktenarchiv.
Das Forum hat mir geholfen, Tkinter zu installieren, dafür möchte ich mich hiermit bedanken, auch wenn ich letzteres nur gelegentlich benutze.
Da ich nicht weiter im Forum posten werde, wünsche ich allen noch ein gutes k+9.
-- wn --
Antworten