![]() |
Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klassen
Wir machen in der Berufsschule gerade Java. Ich bringe mir allerdings so ein paar Dinge im Selbststudium bei, weil mir das in der Schule nicht tief genug geht und auch nicht schnell genug. Zur zeit bin ich gerade beim Thema "Vererbung" und "abstrakte Klassen". Die abstrakten Klassen kenne ich natürlich schon aus Delphi, allerdings habe ich mir bisher wohl noch nie richtig Gedanken gemacht, was für einen Nutzen sie haben und wo man sie einsetzt. Könntet ihr mir diesbezüglich etwas helfen?
|
Re: Siin, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Das Beispiel, welches in den meisten Tutorials verwendet wird, handelt von einer Sammlung von Graphikobjekten. TCircle, TRectangle, TImage und so weiter werden von einer Klasse TGraphic abgeleitet und überschreiben deren Paint-Methode. In TGraphic gibt es jedoch keine sinnvolle Implementierung der Paint-Methode, es ist sogar ein Fehler, diese aufzurufen. Daher sollte sie als abstrakt gekennzeichnet werden. In Java geht man sogar noch einen Schritt weiter: Wenn man TGraphic.Paint nicht aufrufen darf, ergibt es keinen Sinn, überhaupt ein Objekt der Klasse TGraphic zu erzeugen. Die Klasse ist daher abstrakt.
Etwas realistischere Beispiele sind Threads oder Aufträge. Letztere werden in Java mit Interfaces (Runable und Callable) implementiert, welche ja letztlich eine konsequente Erweiterung von abstrakten Klassen sind. |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Man kann eine abstrakte fast mit einem Interface vergleichen. Die abstrakte Klasse selbst kannst du nicht erzeugen, du kannst aber innerhalb der abstrakten Definition irgendwelche Methoden aus der abstrakten Klasse aufrufen. Allerdings implementieren MUSST du sie (genau wie bei Interfaces) in der abgeleiteten Klasse. Damit zwingst du auch den Programmierer, sich im Team an gewisse Konventionen zu halten.
Deine Instanzvariablen dürfen aber natürlich weiterhin vom Typ deiner abstrakten Klasse sein. Nur darfst du nicht dessen Konstruktor direkt aufrufen sondern den aus der abgeleiteten Klasse. Bis dahin seh ich also keinen grossen Unterschied zu einem Interface. Der Unterschied zum Interface ist der, dass du mehrere Interfaces definieren kannst, die eine Klasse implementieren muss, und du diese Klasse über jeden dieser Interfaces ansprechen kannst. Damit immitierst du eine Art Mehrfachvererbung. |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Noch andere Unterschiede zu Interfaces: Man kann einige Methoden bereits implementieren und Felder deklarieren. Außerdem sind abstrakte Klassen meist performanter, gerade in Java kann sich das durchaus bemerkbar machen.
|
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
@Appolonius: dann könnte ich doch einfach bei TGraphic die Paint Methode weglassen, so dass jede abgeleitete Klasse sie selber implementieren muss. Wozu dann eine abstrakte Methode, wenn die abgeleiteten Klassen sie doch selber implementieren müssen? Warum deklariere ich sie denn dann erst in der übergeordneten Klasse?
|
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Wie würdest du dann eine Liste von Graphikobjekten implementieren, die du alle zeichnen lassen kannst?
|
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Zitat:
|
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Zitat:
Will heissen, Du lässt Dir von einer factory eine konkrete Instanz einer Ableitung von TGraphic zurückgeben, benutzt aber eine Referenz auf TGraphic. Wenn Du sie nicht in der abstrakten Basisklasse deklarieren würdest, könntest Du die Paint-Methode gar nicht aufrufen, ohne auf die jeweilige Konkrete Klasse zu casten. |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Wie wäre es mit einem Beispiel:
Wir wollen verschiedene geometrische Figuren (Dreieck, Quadrat, Kreis) verwalten und deren Fläche berechnen können. Die Klassen sollen TDreieck, TQuadrat und TKreis heißen und eine Funktion function BerechneFlaeche(): Double soll bei jeder der Klassen den Flächeninhalt berechnen. Natürlich hat jede Klasse andere Attribute (TKreis hat einen Radius, etc.). Wenn wir jetzt alle drei von einer Klasse TGeometrischeFigur ableiten, könnten wir also beliebige Kreise, Dreiecke, etc. in einem gemeinsamen array of TGeometrischeFigur verwalten. Um noch die Fläche berechnen zu können, muss TGeometrischeFigur logischerweise die Funktion BerechneFlaeche implementieren. Und hier macht es dann keinen Sinn mehr, weil man ja nicht weiß, was man zu berechnen hat. Also kommt das abstrakte ins Spiel. Damit zwingst du (wie oben beschrieben) den Programmierer dazu, die Funktion BerechneFlaeche in jeder abgeleiteten Klasse zu implementieren und kannst sie gleichzeitig (Polymorphismus sei dank) direkt über den Array-Eintrag vom Typ TGeometrischeFigur aufrufen (es wird natürlich jeweils die Richtige aufgerufen). Und da eine Instanz von TGeometrischeFigur hier weitgehend sinnfrei wäre, kann man halt auch die gesamte Klasse als abstrakt kennzeichnen, um das unfreiwillige instanziieren zu unterbinden. Korrigiert mich, wenn ich Blödsinn geschrieben habe :mrgreen: |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Ich glaube, so langsam wird mir das Konzept klar.
|
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
darf ich etwas zwischenfragen?
wenn ich Codewalker richtig verstanden habe, dann ist so etwas möglich? (Dreieck,Rechteck,Kreis,Trapez....)
Delphi-Quellcode:
Gruß K-H
agm = array [0..5] of TGeometrischeFigur ;
for i:=0 to 5 do flaeche:=agm[i].BerechneFläche; |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Jupp das ist möglich, wobei gilt:
Delphi-Quellcode:
Heißt also, du musst für die abstrakten Elemente deines Array konkrete Klassen "createn".
agm[0] := TDreick.Create;
agm[1] := TKreis.Create; [...] |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Jepp, hab mal schnell ein Beispiel geschrieben:
Delphi-Quellcode:
program Tiereklassen;
uses Windows; {$APPTYPE CONSOLE} type TTier = class protected procedure GibLaut; virtual; abstract; end; THund = class(TTier) public procedure GibLaut; override; end; TKatze = class(TTier) public procedure GibLaut; override; end; TKuh = class(TTier) public procedure GibLaut; override; end; procedure THund.GibLaut; begin writeln('Wau'); end; procedure TKatze.GibLaut; begin writeln('Miau'); end; procedure TKuh.GibLaut; begin writeln('Muh'); end; var Tiere: array[0..2] of TTier; begin Tiere[0] := THund.Create; try Tiere[1] := TKatze.Create; try Tiere[2] := TKuh.Create; try Tiere[0].GibLaut; Tiere[1].GibLaut; Tiere[2].GibLaut; finally Tiere[2].Free; end; finally Tiere[1].Free; end; finally Tiere[0].Free; end; readln; end. |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Hallo Nachti1505,
davon bin ich ausgegangen, denn die "konkreten" Klassen (TKreis,TDreieck..) müssen ja erst definiert werden, damit ich die überhaupt erst einmal eine (bzw. die) Flächenberechnungsroutine(n) habe . sonst gibt's doch Fehlermeldungen bzgl. "Abstrakter Methoden". Gruß K-H |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Letztendlich geht es mir um die Frage: "Warum abstrakte Klassen?"
|
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Zitat:
P.S.: Ich könnte auf Wunsch noch ein ausführlicheres Beispiel mit Geometrischen Formen hochladen. |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Ein anderes Beispiel:
In meiner 2D Grafikbibliothek wird die Grafikschnittstelle so abstrahiert, dass man jede beliebige Grafikschnittstelle (sprich OpenGL oder Direct3D) über eine DLL damit verwenden kann. Hierbei liegt die abstrakte Klassendefinition in einer einzelnen Unit, die sowohl von Host-Applikation als auch der DLL eingebunden wird. Die abstrakten Methoden der verschiedenen Klassen werden erst in der DLL implementiert. Vergleiche: Interface: ![]() Implementierung: ![]() |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Zitat:
|
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Hallo Luckie,
Ich denke man könnte die abstrakte Klasse als Prototypen bezeichnen. In meiner Praxis gäbe es so etwas wie TDatenLesen und als konkrete Umsetzung gäbe es TExelLesen3,TExcelLesen4,TExcelLesen95 usw. Im Hauptprogramm arbeite ich nur mit TDatenlesen (bzw. den dort bekannt gemachten Methoden) und in Unterroutinen wird dann die "richtige" Klasse verwendet,bzw. die "richtige" Instanz erstellt. . Ich denke TStrings als abstakte Klasse und Tstringlist als "konkrete" Umsetzung sind auch ein Beispiel; Gruß K-H |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Zitat:
|
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Zitat:
Du hast eine Klasse TKörper, in dieser Klasse kannst Du das Gewicht berechnen in dem Du das Volumen mit dem spezifischem Gewicht des Körpers multipizierst. (Vorausgesetzt alle Körper bestehen nur aus einem Material). Der Körper weiß aber nicht wie sein Volumen berechnet wird. Ein TWürfel und eine TKugel unterscheiden sich in der Volumenberechnung. Ich hoffe es wird Dir in folgendem Beispiel klar. Ein anderes gutes Beispiel findest du auf Deiner Festplatte im Delphi Demos Ordner (ThreadDemo). [edit] Nachtrag: Beim Kompilieren gibt es "nur" eine Warnung wenn Du abstrakte Methoden nicht implementierst. Du kannst eine TKoerper erzeugen aber wenn Du berechneGewicht aufrufst, bekommst du beim berechneVolumen Aufruf eine EAbstractError-Exception. [/edit] Beispiel:
Delphi-Quellcode:
unit Unit2;
interface type TKoerper = class private FspezifischesGewicht: Integer; public function berechneVolumen: Integer; virtual; abstract; function berechneGewicht: Integer; property spezifischesGewicht: Integer read FspezifischesGewicht write FspezifischesGewicht; end; TWuerfel = class(TKoerper) private FLaenge: Integer; public property Laenge: Integer read FLaenge write FLaenge; function berechneVolumen: Integer; override; end; implementation { TKoerper } function TKoerper.berechneGewicht: Integer; begin Result := berechneVolumen * FspezifischesGewicht; end; { TWuerfel } function TWuerfel.berechneVolumen: Integer; begin Result := FLaenge * FLaenge * FLaenge; end; end. |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Zitat:
Nachtrag2: :zwinker: Abstrakte Methoden machen auch dann Sinn, wenn in der Basisklasse noch überhaupt nicht bekannt ist, wie die Methode implementiert werden soll. Um das Beispiel von Mabuse nochmals aufzugreifen, kann man in der abstrakten Klasse zwar erahnen, was das BerechneVolumen einer TKörper Klasse machen soll, aber weil die Geometrie in diesem Stadium noch nicht bekannt ist, kann hier nichts vorgegeben werden. Allerdings das Gewicht des Körpers ist wieder über die generelle Formel Volumen*Volumenmasse definiert, und zwar für alle Körper. Die Methode BerechneGewicht kann also direkt in der Basisklasse komplett implementiert werden. Das konkrete Volumen wird dann aus einer Methode der abgeleiteten Klasse genommen. Du kannst dir natürlich auch vorstellen, dass in der BerechneVolumen eventuell einige generelle Aktionen getroffen werden müssen. In dem Fall deklarierst du wie gehabt die Methode als virtual und in der abgeleiteten Klasse als override. |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Es ist aber eher eine Besonderheit von Delphi, dass man abstrakte Klassen überhaupt instantiieren kann.
|
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
So, in meinem Skript hab eich jetzt folgendes stehen:
Zitat:
|
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Zitat:
|
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Also abstrakte Klassen kenne ich mehr aus Java und nicht aus Delphi
Wenn ich zB. eine Klasse "Spielfigur" habe hat diese eine Methode "walk". Die Spielfiguren selbst sind jetzt jedoch keine "Spielfigur"en sondern zB "Pferd","Hund" etc Die akstrakte Klasse dient im Gegensatz zum Interface jetzt dazu das die davon ageleitete Klasse bereits eine funktionierende Methode hat. Beim interface muss ich die erst bei jeder abgeleiteten Klasse selbst schreiben. Abstrakt macht man das ganze damit man diese Klassen nicht direkt erzeugen kann, sondern erst ableiten muss. |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Zitat:
|
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Streng genommen nein, denn TStrings hat zwar abstrakte Methoden, ist aber nicht selbst als abstrakt deklariert. Das geht auch erst in späteren Delphi-Versionen.
|
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Zitat:
Interfaces haben noch teils ganz anderen Nutzen, denn man kann Instanzen von Klassen, die ein Interface implementieren, direkt über das Interface ansprechen. Wenn das Objetk zum Beispiel von einem Remoting Server kommt, dann braucht der Client noch nicht einmal zu wissen, um welche Klasse es sich handelt. Die Definition des interface reicht ihm völlig aus... Bei abstrakten Klassen ist sowas nicht zu bewerkstelligen... Aber Thema ist ja abstrakte Klassen und nicht Interfaces. |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Ja aber es war ja nicht die Frage nach dem Sinn der Interfaces, sondern der abstrakten Klassen.
Luckie: Ich weis das es abstrakte Klassen in Delphi gibt, es ist nur nicht so offensichtlich wenn man nicht so oft damit arbeitet. Bei Java hab ich das öfters gemacht,deswegen war es mir dort geläufiger. |
Re: Sinn, Nutzen und Einsatzmöglichkeit von abstrakten Klass
Hallo Luckie,
schon allgemein das Wort abstrakt beschreibt schon einiges. Nehmen wir mal als Beispiel ein Hund und eine Katze. Beide der Tiere kann man abstrakt ansehen. Man könnte diese unter Katigorieren bzw. Funktionen einordenen, wie sitz machen, mit Schwanz wedeln und ähnliches. Mit abstrakten Klassen kannst du genau dies auch umsetzen. Eigentlich könnte man dies auch mit einem Interface implementieren. Hier einige nütze Links:
HTH zero_x |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:33 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