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.
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