Buchempfehlung
Windows System Programming
Windows System Programming
Das Kompendium liefert viele interessante Informationen zur Windows-Programmierung auf Englisch. [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

Tutorial

OOP für Anfänger

von MitgliedStueberSeite 1 von 1

Erforderliches Vorwissen

Du solltest wissen, was Variablen und BefehlsreferenzeintragUnterprogramme sind. Außerdem solltest du bereits allgemeine Erfahrung mit FreeBASIC haben. Wissen über BefehlsreferenzeintragPointer ist nützlich, aber nicht erforderlich.

OOP - was ist das?

Die Abkürzung OOP steht für "Ojektorientierte Programmierung". Was das bedeutet, wirst du in diesem Tutorial kennenlernen. OOP ist ein eigenes Konzept, das von zahlreichen Programmiersprachen unterstützt wird. FreeBASIC unterstützt bisher (noch) nicht alle OOP-Mittel, aber das was noch fehlt, dürfte dich jetzt noch eher weniger interessieren.

Als Anschauungsobjekt verwenden wir in diesem Tutorial ein ganz vereinfachtes Software-Abbild eines Autos.

Strukturen

Strukturen bzw. structs (in FreeBASIC BefehlsreferenzeintragType genannt), sind im Allgemeinen Ansammlungen von Variablen. Stell dir vor, du wolltest in deinem Programm ein Auto verwalten. Es ist jetzt noch egal, ob du es zeichnen oder damit Berechnungen anstellen willst.
Ein Auto hat einige Eigenschaften wie zum Beispiel:

Bisher würdest du dies vermutlich so als Programm umsetzen:

dim Farbe as uinteger
dim Laenge as double
dim Geschwindigkeit as double
dim Raeder as integer

Jetzt wirst du sehr wahrscheinlich irgendwann einmal mehr als ein Auto verwenden wollen, doch was tust du, wenn du zwei Autos "machen" möchtest? Vielleicht Folgendes?

dim Farbe1 as uinteger
dim Laenge1 as double
dim Geschwindigkeit1 as double
dim Raeder1 as integer

dim Farbe2 as uinteger
dim Laenge2 as double
dim Geschwindigkeit2 as double
dim Raeder2 as integer

Auf Dauer wird das sehr unübersichtlich und du wirst durcheinander kommen, abgesehen davon, dass die Vorgehensweise noch weitere Nachteile hat.
Die Lösung ist in diesem Fall eine Struktur, ein BefehlsreferenzeintragType. Dabei handelt es sich um einen selbst erstellten Datentypen (vergleiche dazu die standardmäßig vorhandenen wie BefehlsreferenzeintragINTEGER), der sich aus mehreren Untervariablen zusammensetzt. Die Definition eines Type startet man mit dem Schlüsselwort TYPE gefolgt von einem Namen (Bezeichner), in diesem Fall Auto. Jeder Type muss einen solchen Namen haben. Das Beispiel mit dem Auto würde unter Verwendung eines TYPEs so aussehen:

type Auto
  Geschwindigkeit as double
  Farbe as uinteger
  Laenge as double
  Raeder as integer
end type

Wichtig: Noch wurde keine Variable angelegt, das heißt es befindet sich im Speicher noch kein Platz für einen solchen Auto-Datensatz. Der soeben definierte TYPE stellt nur eine Bauanleitung für diese individuell zusammengesetzten Verbundvariablen dar. Während der TYPE mit einer Backform vergleichbar ist, wären Variablen, die man dieser Bauanleitung entsprechend erzeugt, die Muffins!

TYPE und Variable im Vergleich: Klasse und Objekt

So, jetzt hast du einen Type für Autos, wie geht's weiter? Du kannst jetzt das Wort "Auto" wie einen Datentyp verwenden. Das heißt, mit

dim Gelaendewagen as Auto

legt eine Variable mit dem Namen Gelaendewagen vom Typ Auto an.
Speichern kann man nur in die so angelegten Variablen, nicht in den TYPE selbst. Also ähnlich, wie man auch beim Backen nicht die Backform isst, sondern nur die Muffins. ;-)

In Hinblick auf den TYPE spricht man übrigens von der Klasse, während die so erzeugten Auto-Variablen Objekte oder Instanzen genannt werden.

Auf Variablen zugreifen

Du hast jetzt also einen Type für Autos und kannst ganz leicht neue Autos anlegen. Wie kommt man jetzt an den Inhalt eines Autos heran, also an die enthaltenen Variablen? Die Lösung ist der BefehlsreferenzeintragPunkt-Operator. Das sieht dann ungefähr so aus:

dim auto1 as Auto
auto1.Raeder = 4

Der Zugriff auf die "Mitgliedsvariablen" erfolgt also über den Punkt zwischen "auto1" und "Raeder".

Ein Sonderfall ist der Zugriff bei einem BefehlsreferenzeintragZeiger auf ein Auto. Wenn du noch nicht weißt, was Zeiger sind, ist das nicht schlimm für den Rest dieses Tutorials. Falls doch, hier eine Anmerkung dazu (kann übersprungen werden):
Hast du einen Zeiger auf ein Auto (z. B. mit BefehlsreferenzeintragNEW angelegt), funktioniert der Zugriff fast genauso mit dem Unterschied, dass du anstatt eines Punktes einen BefehlsreferenzeintragPfeil ("->") verwendest.

Initialisieren

Ein Auto hat im Normalfall immer die gleichen Ausgangswerte, z.B. wird die Anzahl der Räder stets 4 sein. Jedes Mal, wenn du ein Auto erstellst, müsstest du diesen Wert erst mal setzen, denn sonst würden die numerischen Variablen am Anfang einfach alle mit 0 belegt. Um sich die Arbeit zu sparen, kannst du einen so genannten Konstruktor verwenden. Ein Konstruktor ist ein Unterprogramm (BefehlsreferenzeintragSub), das immer automatisch aufgerufen wird, wenn eine Variable mit deinem Type als Datentyp erzeugt wird.

type Auto
  declare constructor ()

  Geschwindigkeit as double
  Farbe as uinteger
  Laenge as double
  Raeder as integer
end type


constructor Auto()
  Raeder = 4
end constructor

So wird die Anzahl der Räder immer auf 4 gesetzt, wenn ein Auto erzeugt wird, ohne dass du etwas dazu tun musst. Der Konstruktor (in FreeBASIC stets mit C am Anfang geschrieben, weil englisch!) wird für ein so erzeugtes Auto-Objekt sofort bei dessen Erstellung aufgerufen. Er ist sozusagen eine Aufbauanleitung für das Objekt.
Ein Konstruktor darf keinen BefehlsreferenzeintragRückgabewert haben, aber BefehlsreferenzeintragParameter kannst du ihm geben. Das funktioniert genau so wie bei BefehlsreferenzeintragFunktionen und BefehlsreferenzeintragSubs. Wenn du etwas verschieden große Autos haben möchtest, kannst du dies schon über den Konstruktor mitteilen:

type Auto
  declare constructor (byval l as double) 'l steht für die Wunschlänge

  Geschwindigkeit as double
  Farbe as uinteger
  Laenge as double
  Raeder as integer
end type


constructor Auto(byval l as double)
  Raeder = 4
  Laenge = l
end constructor

dim auto1 as Auto = Auto(3)  'Auto mit 3m Länge erstellen

Dieser Code würde ein Auto erzeugen, das in der Variable Laenge den Wert 3 gespeichert hätte.

Neben einem Konstruktor kann auch noch ein sog. Destruktor vorgesehen werden. Ein Destruktor wird mit dem Schlüsselwort BefehlsreferenzeintragDESTRUCTOR und ansonsten gleich wie BefehlsreferenzeintragCONSTRUCTOR verwendet. Der Unterschied ist, dass ein Destruktor aufgerufen wird, wenn die Variable zerstört bzw. gelöscht wird. Dies geschieht entweder...

Der Destruktor kann zum "Aufräumen" bzw. Freigeben von nicht mehr benötigtem Speicherplatz benutzt werden. Ein Destruktor darf keine Parameter haben.

Subs und Funktionen

Bisher hatte der Type nur Variablen und einen Konstruktor (und ggf. auch einen Destruktor), aber Types können noch viel mehr! Du kannst auch Funktionen und Subs in einen Type integrieren, sodass das Auto zu seinen Eigenschaften noch Verhalten erhält. Ein Auto könnte zum Beispiel ein Sub beinhalten, das es zeichnet.

type Auto
  declare sub zeichne ()

  Geschwindigkeit as double
  Farbe as uinteger
  Laenge as double
  Raeder as integer
end type

sub Auto.zeichne ()
  'Hier würde der Code hinkommen, der das Auto zeichnet
end sub

Das "Funktionsangebot" Zeichne, das das Auto-Objekt bereitstellt, heißt Methode.

Wie du siehst, wird die Funktion ganz normal deklariert, aber bei der Implementierung wird angegeben, dass die Funktion zum Type "Auto" gehört. Aufgerufen wird die Funktion gleich wie eine Variable des Types, also mit Punkt:

dim auto1 as Auto
auto1.zeichne()

Vorteile von OOP

So, du hast nun das Basiswissen über OOP. Jetzt stellst du dir sicher die Frage, warum du so viel neues, Abstraktes lernen und verwenden sollst, wenn du bisher auch ohne ausgekommen bist.
Der erste Vorteil, den du bemerkst, ist, dass der Code sehr viel übersichtlicher wird. Du musst, um beispielsweise das Auto zu zeichnen, nicht mehr überall den Zeichencode eintippen oder einer Zeichenfunktion die ganzen Parameter (Farbe, Länge, ...) übergeben:

'Schlechter:
SUB ZeichneEinAuto (ByVal Farbe As UInteger, ByVal Laenge As Double, ....)
   '...
END SUB

Ein weiterer Vorteil ist, dass dein Code so sehr viel besser wiederverwendbar wird. Wenn du die ganzen Dinge im Zusammenhang mit dem Auto überall im Quelltext verteilst, wird es schwer, bei einem anderen Projekt den Code des Autos wieder zu verwenden. Deine Autoklasse hingegen kannst du leicht in einem anderen Programm einbinden, in dem du wieder Auto-Objekte brauchst. Die passenden Routinen für die Autos liefern die Auto-Objekte in Form von Methoden ja bereits mit.
Wenn du OOP arbeitest, musst du nur den Code des Types kopieren und kannst den Type in jedem Projekt wiederverwenden.
Wie du oben gesehen hast, wird dir OOP auch beim Verstehen deines eigenen Programms helfen. Willst du viele Autos anlegen, wirst du bald nicht mehr verstehen, welche Funktion oder Variable jetzt für welches Auto war. Alles in allem lohnt sich OOP auf Dauer, auch wenn du es am Anfang wahrscheinlich für sinnlos halten wirst. Das ist nichts Besonderes, mir ging es auch so. Ich dachte mir "Warum soll ich das so machen, klappt doch auch so wunderbar". Wirklich überzeugt von den Vorteilen wirst du erst, wenn du ein großes Projekt mit OOP programmierst.


Ausblick auf die Zukunft

Seit einiger Zeit wird an erweiterten OOP Features gearbeitet, z.B. Vererbung und virtuellen Funktionen. Diese Features wirst du vermutlich am Anfang noch nicht brauchen, aber sie sind für größere Programme sehr nützlich. Die FreeBASIC-Entwickler arbeiten seit einiger Zeit daran und die neuesten Entwicklungen lassen darauf hoffen, dass das Warten in nicht all zu langer Zeit ein Ende hat.
Dieses Tutorial wird in kurzer Zeit fortgesetzt durch ein Tutorial zu komplexeren OOP-Mitteln.

 

Zusätzliche Informationen und Funktionen
  • Das Tutorial wurde am 23.07.2010 von MitgliedStueber angelegt.
  • Die aktuellste Version wurde am 24.07.2010 von AdministratorSebastian gespeichert.
  Bearbeiten Bearbeiten  

  Versionen Versionen