AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Warum und wann eine Klasse benutzen

Ein Thema von IMPEGA · begonnen am 16. Okt 2013 · letzter Beitrag vom 17. Okt 2013
Thema geschlossen
Seite 2 von 2     12   
Popov
(Gast)

n/a Beiträge
 
#1

AW: Warum und wann eine Klasse benutzen

  Alt 16. Okt 2013, 19:13
Ich brauche nur den Sinn der dahinter steckt.
Ja, es gibt einen gute Sinn dahinter.

Ich hab irgendwann einen Artikel gelesen in dem über die Frage philosophiert wurde ob Klassen uns das Leben leichter machen, alternativ ob das Arbeiten dadurch schneller wird. An den genauen Wortlaut kann ich mich jetzt nicht mehr erinnern, aber aber die Antwort war in etwa: mit Klassen zu arbeiten sparrt keine Zeit im Vergleich zu der klassischen Prozeduren/Unit-Sammlungen. Ob das stimmt muss jeder für sich beantworten, es war aber die Antwort des Artikels. Deswegen würde ich die Frage nicht in die Richtung stellen. Ich persönlich bin eher der Unit-Prozedur-Sammlungen Typ, denn eine Klasse macht immer mehr Arbeit (meine Meinung) und es muss nicht immer eine Klasse sein.

Trotzdem, eine Klasse ist eine feine Sache, denn sie bietet Möglichkeiten.

Im Grunde ist eine Klasse zum Teil auch nichts anderes als eine Prozedur-Sammlung. Die wären dann eher die Methoden. Also Prozeduren und Funktionen einer Klasse. Dann hat die Klasse aber auch Eigenschaften. Ich beschreibe das gerne als intelligente Variablen, denn wenn ich einer normalen Variable "Zitrone", die nur grün oder gelb sein kann, die Farbe blau zuweise, juckt es sich nicht. In einer Klasse kann man den Zuweisungsprozess über eine Prozedur leiten. Das geht automatisch, so dass der Programmierer sich gar nicht drum kümmern muss. Diese Arbeit hat sich der Programmierer der Klasse gemacht. Der eigentliche Programmierer muss sich nicht mehr drum kümmern. Das kann man zwar auch mit einer normalen Variable und Prozedur oder Funktion auch machen, aber dann stellt sich die Frage: warum in dem Fall nicht gleich eine Klasse schreiben? Sie ist ja dazu gemacht solche Aufgaben zu übernehmen.

Delphi-Quellcode:
type
  TZitrone = class
  private
    FZitronenfarbe: String;
    procedure ZFarbe(a: String);
  public
    constructor Create;
    property Zitronenfarbe: string read FZitronenfarbe write ZFarbe;
  end;

constructor TZitrone.Create;
begin
  FZitronenfarbe := 'gelb';
end;

procedure TZitrone.ZFarbe(a: String);
begin
  if (LowerCase(a) = 'grün') or (LowerCase(a) = 'gelb') then
    FZitronenfarbe := a
  else
    FZitronenfarbe := 'gelb';
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Zitrone: TZitrone;
begin
  Zitrone := TZitrone.Create;
  Zitrone.Zitronenfarbe := 'blau';
  ShowMessage(Zitrone.Zitronenfarbe);
  Zitrone.Free;
end;
Das kleine Beispiel verdeutlicht vielleicht was ich meine. In der Prozedur Button1Click gebe ich als Zitronenfarbe blau an. Zitronenfarbe scheint eine Variable zu sein, ist aber eine Eigenschaft. Betrachtet man property Zitronenfarbe (unter Type) wird der Schreibzugriff auf die Eigenschaft an die Prozedur ZFarbe umgeleitet. Diese Prüft den Wert und übernimmt die Speicherung in FZitronenfarbe. Wird gelesen, wird direkt aus der Variable gelesen.

Bei der Gelegenheit wird bei Create der Zitrone die Farbe gelb zugewiesen. Muss man also auch nicht mehr selbst machen. All das kann man zwar auch selbst mit Prozeduren und Funktionen machen, den Job übernimmt aber die Klasse für einen. Aufgaben werden sozusagen im Hintergrund erledigt. Die Entwicklung ist vielleicht mit mehr Aufwand verbunden, aber später holt man das wieder raus. Bei Prozeduren-Lösung müsste man sich selbst um alles kümmern.

Das ist natürlich nur eine der Vorteile von Klassen. Eine weitere wäre zum Beispiel die Vererbung. Man kann eine bestehende Klasse nehmen und sie mit paar Klicks erweitern.

Delphi-Quellcode:
type
  TBitmap64 = class(TBitmap)
  private
  public
    constructor Create;
  end;

constructor TBitmap64.Create;
begin
  inherited;
  Self.Width := 64;
  Self.Height := 64;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  Bmp64: TBitmap64;
begin
  Bmp64 := TBitmap64.Create;
  Canvas.Draw(0, 0, Bmp64);
  Bmp64.Free;
end;
Wenn ich zum Beispiel ständig eine Bitmap mit den Massen 64 x 64 Pixel brauche und mich das ständige Wertezuweisen stört, könnte ich mir meine eigene Bitmap Klasse schreiben die bereits die richtige Abmessungen besitzt. Vererbung bietet noch mehr Möglichkeiten, aber das wäre etwas simples als Beispiel.

Wie schon oben erwähnt, man kann auch ohne eigene Klassen programmieren, aber gelegentlich lohnt es sich Klassen zu schreiben.

Geändert von Popov (16. Okt 2013 um 19:16 Uhr)
 
IMPEGA

Registriert seit: 19. Jan 2008
Ort: Brhv
110 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

AW: Warum und wann eine Klasse benutzen

  Alt 16. Okt 2013, 19:47
Die letzten beiden Antworten sind genau das was ich gesucht habe.
Ja @stahli genau so solltest du es verstehen.
Genau derart Antworten habe ich gesucht.
Ich benutze schon ziemlich lange eigene Klassen, habe mich aber nie wirklich damit beschäftigt.
Nun hat es angefangen mich ernsthafter zu interessieren, und siehe da, es tauchten Fragen auf.
Auch ein Dank an @Popov , sehr gut erklärt. Das sind Gründe genug um mehr über OOP zu lesen.
Es ist nämlich nicht so dass es ganz neu für mich ist, nun möchte ich es aber besser und sinnvoller machen.
Danke noch Mal.
 
Popov
(Gast)

n/a Beiträge
 
#3

AW: Warum und wann eine Klasse benutzen

  Alt 16. Okt 2013, 20:02
Ja, manchmal muss erst der berühmte Groschen fallen. Ich hatte mal das Problem mit begin und end bei Pascal, da ich mit dem C64, bzw. TI-99/4A Basic angefangen habe und das Basic diesen "Unsinn" nicht brauchte. Ich konnte erst weiter machen, als ich verstanden habe, dass auch Basic ein begin und end hat, nur versteckt, bzw. indirekt (siehe next bei for). Im Grunde das Gleiche in grün. Manchmal muss einfach der Groschen fallen.
 
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#4

AW: Warum und wann eine Klasse benutzen

  Alt 16. Okt 2013, 20:36
Ein weiterer, sehr toller Aspekt an OOP ist Polymorphie. Für mich ist das vielleicht sogar der entscheidende Punkt, da man ihn im Gegensatz zu Kapselung und Vererbung eigentlich nicht gescheit ohne Klassen simulieren kann (technisch möglich ist es natürlich, ist dann aber nicht mehr wirklich eleganter als Alternativen).

Delphi-Quellcode:
type
  TShape = class
  protected
    FLeft, FTop, FSize: integer;
  public
    procedure DrawTo(Canvas: TCanvas); virtual; abstract;
    property Left: integer read FLeft write FLeft;
    property Top: integer read FTop write FTop;
    property Size: integer read FSize write FSize;
  end;

  TCircle = class(TShape)
  public
    procedure DrawTo(Canvas: TCanvas); override;
  end;

  TSquare = class(TShape)
  public
    procedure DrawTo(Canvas: TCanvas); override;
  end;

implementation

procedure TCircle.DrawTo(Canvas: TCanvas);
begin
  Canvas.Ellipse(Left, Top, Left + Size, Top + Size);
end;

procedure TSquare.DrawTo(Canvas: TCanvas);
begin
  Canvas.Rectangle(Left, Top, Left + Size, Top + Size);
end;
Delphi-Quellcode:
type
  TMyForm = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormPaint(Sender: TObject);
  private
    FShapes: array[0..4] of TShape;
  end;

implementation

procedure TMyForm.FormCreate(Sender: TObject);
begin
  // *Irgendwelche* Formen z.B. in einem Array/Liste speichern.
  // Konkreter Typ ist egal, solange sie nur von TShape erben.
  for i := low(Shapes) to high(Shapes) do
  begin
    if Odd(i) then
      Shapes[i] := TCircle.Create
    else
      Shapes[i] := TSquare.Create;

    Shapes[i].Size := i * 5;
    Shapes[i].Left := i * 20;
    Shapes[i].Top := 0;
  end;
end;

procedure TMyForm.FormPaint(Sender: TObject);
begin
  // Wir können jetzt alle diese verschiedenen Objekte mit dem gleichen
  // Code verarbeiten, obwohl es sich um verschiedenartige Klassen
  // handelt und jeweils spezialisierter Code ausgeführt wird
  // -> man spart sich u.U. etliche Case-Strukturen, die den Code
  // sonst unübersichtlich und fehleranfällig machen würden
  for i := low(Shapes) to high(Shapes) do
    Shapes[i].DrawTo(Canvas);
end;

procedure TMyForm.FormDestroy(Sender: TObject);
begin
  for i := low(Shapes) to high(Shapes) do
    Shapes[i].Free;
end;
Mit records geht das einfach nicht so schön... vor allem nicht, wenn man später das Programm leicht um weitere Spezialisierungen erweitern können will.
 
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.667 Beiträge
 
Delphi 12 Athens
 
#5

AW: Warum und wann eine Klasse benutzen

  Alt 16. Okt 2013, 20:47
Die 3 großen Stichworte zur OOP lauten Kapselung, Vererbung und Polymorphie. Kurze vereinfachte Erläuterung zu den einzelnen Stichworten:
Kapselung:
Eine Klasse stellt die Konsistenz ihrer Daten selbständig sicher. Das erreicht sie dadurch, dass sie keinen direkten Zugriff auf diese gewährt, sondern lediglich über Schnittstellen in Form von Properties. Außerdem kann sie über Sichtbarkeitsebenen (private, protected, public) bestimmen, wer auf welche Daten und Methoden Zugriff haben soll.
Vererbung:
Wird eine Klasse von einer anderen abgeleitet, so erbt sie automatisch deren Properties und Methoden, ohne dass eine einzige zusätzliche Zeile Code nötig wäre. So lässt sich eine Klassenhierarchie aufbauen, in der die Funktionalität und/oder Spezialisierung von oben nach unten stetig zunimmt.
Polymorphie:
Vielgestaltigkeit, d.h. man kann z.B. einen Funktionsparameter vom Typ einer bestimmten Basisklasse deklarieren und sichergehen, dass auch davon abgeleitete Klassen dazu passen, ohne deren exakten Typ kennen zu müssen. Das klingt vielleicht etwas abstrakt, daher mal ein Beispiel:
Delphi-Quellcode:
type
  TTier = class
  public
    procedure GibLaut; virtual; abstract;
  end;

  THund = class(TTier)
  public
    procedure GibLaut; override;
  end;

  TKatze = class(TTier)
  public
    procedure GibLaut; override;
  end;

...

procedure THund.GibLaut;
begin
  ShowMessage('Wuff');
end;

procedure TKatze.GibLaut;
begin
  ShowMessage('Miau');
end;

procedure MachKrach(Tier: TTier);
begin
  Tier.GibLaut;
end;
In der Prozedur MachKrach ist ein Parameter vom Typ TTier deklariert. Es ist der Prozedur also vollkommen wurscht, ob es sich dabei nun um einen Hund oder eine Katze handelt, sie weiß aber, dass das Tier auf jeden Fall über eine Methode GibLaut verfügt, so dass sich diese über die TTier-Klasse aufrufen lässt.

Man kann natürlich auf den ganzen Schmu auch verzichten, macht es sich damit aber meist unnötig schwer. Das soll aber nicht heißen, dass OOP-Programmierung nun die Lösung aller Probleme wäre, man kann auch in OOP Mist schreiben, ebenso wie man auch prozedural gute Programme hinbekommen kann, der Aufwand ist aber (zumindest bei Neuentwicklungen) um Einiges größer.

P.S.: Zwischenzeitlich wurde zwar ein neuer Post geschrieben, trotzdem schicke ich das mal ab.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
 
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#6

AW: Warum und wann eine Klasse benutzen

  Alt 17. Okt 2013, 11:13
Vererbung:
Wird eine Klasse von einer anderen abgeleitet, so erbt sie automatisch deren Properties und Methoden, ohne dass eine einzige zusätzliche Zeile Code nötig wäre. So lässt sich eine Klassenhierarchie aufbauen, in der die Funktionalität und/oder Spezialisierung von oben nach unten stetig zunimmt.
Nichts für ungut, aber solche Erklärungen können einem den ganzen Spaß vertreiben.
Schön daß man so etwas machen kann, aber wofür ist es gut?
Was bringt es mir?
Wenn Olaf schreibt:
Zitat:
Im bisherigen Schema mußt du nun ALLE ROUTINEN, die sich mit Dateien befassen, ERNEUT schreiben. Also Routinen wie
- OpenMP3File
- ProcessMP3Header
Dann ist das wie ein Buhmann für kleine Kinder; ich kann mit Copy&Paste arbeiten, da schrecken die paar Zeilen Code nicht.

Wenn man mit Klassen arbeitet wird das dann noch etwas einfacher, da die "Code-Organisation" etwas übersichtlicher wird. Ebenso kann man innerhalb der Klasse arbeiten wie man will, da die Schnittstellen nach draußen definiert sind und ich keine Seiteneffekte beachten muß.

Schau ich mir VBA an, dann weiß ich wie OOP sich nicht präsentieren sollte, die gleiche Information in 5 verschiedenen Klassen und der Nutzer weiß nicht wofür es gut sein soll.

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
 
Thema geschlossen
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:42 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz