AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi Interface richtig verstanden?

Interface richtig verstanden?

Ein Thema von EdAdvokat · begonnen am 3. Mai 2019 · letzter Beitrag vom 9. Mai 2019
Antwort Antwort
Seite 1 von 4  1 23     Letzte » 
EdAdvokat

Registriert seit: 1. Mai 2016
Ort: Berlin
414 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#1

Interface richtig verstanden?

  Alt 3. Mai 2019, 16:43
Hallo zusammen,
ich habe mich etwas mit dem Thema Interface beschäftigt und daraus entstand ein kleines Übungsbeispiel, um zu überprüfen ob ich das Thema
Interface im Ansatz verstanden habe.
Bitte schaut doch mal darüber. Für Hinweise und Korrekturen bin ich dankbar. Sollte es ok sein, wäre meine Freude fast grenzenlos.
Ich will die Sache aber später noch weiterführen.
Danke
Angehängte Dateien
Dateityp: zip figur_interface1.zip (53,5 KB, 18x aufgerufen)
Norbert
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
3.896 Beiträge
 
Delphi 12 Athens
 
#2

AW: Interface richtig verstanden?

  Alt 3. Mai 2019, 16:54
Mal schnell im Notepad drübergesehen, sieht doch erstmal ganz OK aus.

Die Tutorials hier und hier kennst du ?
  Mit Zitat antworten Zitat
EdAdvokat

Registriert seit: 1. Mai 2016
Ort: Berlin
414 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#3

AW: Interface richtig verstanden?

  Alt 3. Mai 2019, 17:33
ich will meine Frage erweitern: Wenn ich also ein Basisobjekt
Delphi-Quellcode:
type
  TFigure = class(TInterfacedObject, IFigur)
   FSeiteA : Double;
   FSeiteB : Double;
   function Umfang: Double;
   function Flaecheninhalt: Double;
 end;
nach der Dekleration des Interface erstelle und davon dann die weiteren Figuren (Quadrat, Dreieck usw) ableite, wird dann auch das TInterfacedObject vererbt,
dass für die Speicherfreigabe verantwortlich ist?
Kann ich also mit
Delphi-Quellcode:
 type
 TQuadrat = class (TFigure, IFigur)
  FSeiteA : double;
  FSeiteB : double;
  function Umfang:double;
  function Flaecheninhalt:double;
 end;
weitere Klassen vererben, die dann auch TInterfacedObject erhalten?
Norbert
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.108 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: Interface richtig verstanden?

  Alt 3. Mai 2019, 17:44
Die Antwort auf deine Frage ist "Ja":
  • TFigure ist ein TInterfacedObject
  • TQuadrat ist ein TFigure, folglich ist es auch ein TInterfacedObject und bringt alles mit (wie z.B. Interface-Unterstützung)

Aber:
  1. Du deklarierst die Felder "FSeiteA" und "FSeiteB" einmal in TFigure, und dann noch einmal in "TQuadrat".
  2. Mit den Methoden verhält es sich ähnlich: Dass die Methoden in "TFigure" nicht virtual sind ist eigentlich ein Fehler. Hast du das mit virtuellen Methoden ("Polymorphie") verstanden? Du brauchst keine Interfaces für Polymorphie, aber umgekehrt muss man das verstanden haben bevor man sich an Interfaces wagt
  3. Sicher ist es nur ein Beispiel, aber mit der Klasse TFigure hast du eigentlich nichts gewonnen. Wie würdest du denn Umfang() oder Flächeninhalt() allgemeingültig implementieren wollen? Die Klasse an sich ist völlig abstrakt. Um das zu signalisieren kannst du z.B. statt TFigure = class(TInterfacedObject, IFigur) auch schreiben TFigure = class abstract(TInterfacedObject, IFigur) . Damit bekämst du auch eine Compiler-Warnung wenn du eine TFigure statt z.B. einem TQuadrat erstellst, denn ein TFigure ist nur eine abstrakte Vorlage.
  Mit Zitat antworten Zitat
EdAdvokat

Registriert seit: 1. Mai 2016
Ort: Berlin
414 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#5

AW: Interface richtig verstanden?

  Alt 3. Mai 2019, 18:14
Danke
zum ersten Punkt: Das habe ich bereits selbst erkannt und verändert. Wenn FSeiteA und FSeiteB im Basisobject deklariert sind, müssen sie nicht nochmals im abgeleiteten Objekt aufgeführt werden.
Punkt 2 habe ich noch nicht so richtig verstanden. Sicher gibt es keine allgemeingültige Formel für Umfang und Flächeninhalt versch. Figuren.
Diese habe ich jedoch dann in den jeweiligen Klassen konkret umgesetzt und wie ich glaube, funktioniert das auch exakt.
Punkt 3 habe ich befolgt und
TFigure = class abstract(TInterfacedObject, IFigur) eingefügt.
Norbert
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.108 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: Interface richtig verstanden?

  Alt 3. Mai 2019, 18:56
zu Punkt 2:

Richtig, es gibt keine allgemeingültige Formel. Die in den entsprechenden Klassen dann umzusetzen ist völlig richtig.
Ohne die Schlüsselwörter "virtual" und "override" gibt es allerdings ein Problem - Wenn du eine Variable vom Typ IFigur hast weiß er nicht dass die wirkliche Bestimmung der Fläche nicht in der Klasse (TFigure) sondern in einer Unterklasse steckt.

Ich habe hier einmal ein kurzes Komplettbeispiel gemacht, allerdings mit Tieren statt Formen 😉

https://gist.github.com/JensMertelme...509caa07a057a6
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
3.896 Beiträge
 
Delphi 12 Athens
 
#7

AW: Interface richtig verstanden?

  Alt 4. Mai 2019, 07:57
Das Interface ist ein Vertrag welche Funktionen dein Objekt haben soll.
Das kann mit oder ohne Vererbung sein.
Ja nachdem worum es geht kann Beides sinnvoll sein.

Bei Figuren wäre das virtuelle Ableiten wirklich sinnvoller, damit die Basisklasse gemeinsame Figuren-aufgaben übernehmen kann, ohne in den abgeleiteten Klassen das zu wiederholen.
Die virtuellen Funktion können dann aber bei Bedarf die Basisfunktionen überschreiben,
wenn es notwendig ist.
Z.B. ein Polyeder wäre nur mit x,y nicht mehr abbildbar, und müsste deshalb intern anders aufgebaut sein.

Der Vertrag zum Abfragen Fläche bleibt aber trotzdem gleich.
  Mit Zitat antworten Zitat
EdAdvokat

Registriert seit: 1. Mai 2016
Ort: Berlin
414 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#8

AW: Interface richtig verstanden?

  Alt 4. Mai 2019, 10:14
Danke für eure Hinweise. Ich habe es also etwas verändert und es läuft gut. Nun möchte ich noch etwas tiefer in die Problematik Interface einsteigen.
Delphi-Quellcode:
unit logic;

interface

uses Vcl.Dialogs;

Type
IFigur = interface
 ['{921A6F17-0D63-40EC-82FD-F60CB5F66DC3}']
   function Umfang:double;
   Function Flaecheninhalt:double;
end;

type
  TFigure = class abstract(TInterfacedObject, IFigur)//Basis_Class
  private
   FSeiteA : Double;
   FSeiteB : Double;
  strict protected
   function Umfang: Double;virtual;
   function Flaecheninhalt: Double;virtual;
  public
    property SeiteA: Double read FSeiteA write FSeiteA;
    property SeiteB: Double read FSeiteA write FSeiteB;
 end;

type
 TQuadrat = class (TFigure, IFigur) //class Decleration mit Hinweis auf IFigur
  strict protected //TInterfacedObject übernimmt die Freigabe d. Objects
    function Umfang:double;override;
    function Flaecheninhalt:Double;override;
  public
    property Umfangber: Double read Umfang;
    property Flaechenber: Double read Flaecheninhalt;
 end;

type
 TDreieck = class(TFigure, IFigur)
  private
   FSeiteC : double;
   FHoehe : Double;
  strict protected
   function Umfang:double;override;
   function Flaecheninhalt:double;override;
  public
   property SeiteC: Double read FSeiteC write FSeiteC;
   property Hoehe: Double read FHoehe write FHoehe;
   property Umfangber: Double read Umfang;
   property Flaechenber: Double read Flaecheninhalt;
 end;

type
 TTrapez = class(TFigure, IFigur)
  private
   FSeiteC : Double;
   FSeiteD : Double;
   FHoehe : double;
  strict protected
   function Umfang:double;override;
   function Flaecheninhalt:double;override;
  public
    property SeiteC: Double read FSeiteC write FSeiteC;
    property SeiteD: Double read FSeiteD write FSeiteD;
    property Hoehe: Double read FHoehe write FHoehe;
    property Umfangber: Double read Umfang;
    property Flaechenber: Double read Flaecheninhalt;
 end;

implementation

  { TQuadrat }

function TQuadrat.Flaecheninhalt: double;
begin
  Result:=FseiteA*FSeiteB;
end;

function TQuadrat.Umfang: double;
begin
  Result:=2*FseiteA+2*FseiteB;
end;

{ TDreieck }

function TDreieck.Flaecheninhalt: double;
begin
 Result:=FSeiteA*FSeiteB/2;
end;

function TDreieck.Umfang: double;
begin
   Result:=FSeiteA+FSeiteB+FSeiteC;
end;

 { TTrapez }

function TTrapez.Flaecheninhalt: Double;
begin
  result:=(FSeiteA+FSeiteC)/2*FHoehe;
end;

function TTrapez.Umfang: Double;
begin
  Result:=FSeiteA+FSeiteB+FSeiteC+FSeiteD;
end;

{ TFigure }

function TFigure.Flaecheninhalt: Double;
begin
  Result:=Flaecheninhalt;
end;

function TFigure.Umfang: Double;
begin
  Result:=Umfang;
end;

end.
und das MainForm:
Delphi-Quellcode:
unit uMain;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, logic, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    lbl1: TLabel;
    btn1: TButton;
    edt1: TEdit;
    btn2: TButton;
    edt2: TEdit;
    lbl2: TLabel;
    lbl3: TLabel;
    btn3: TButton;
    edt3: TEdit;
    lbl4: TLabel;
    lbl5: TLabel;
    lbl6: TLabel;
    lbl7: TLabel;
    btn4: TButton;
    lbl9: TLabel;
    edt4: TEdit;
    edt5: TEdit;
    lbl10: TLabel;
    lbl11: TLabel;
    procedure btn1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btn2Click(Sender: TObject);
    procedure btn3Click(Sender: TObject);
    procedure btn4Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btn1Click(Sender: TObject);
begin
  Close;
end;

procedure TForm1.btn2Click(Sender: TObject);
var MyFigure: TQuadrat;
begin
  MyFigure:=TQuadrat.Create; //Freigabe nicht erf., da TInterfacedObject dies übernimmt
  try
  MyFigure.SeiteA:=strtoint(edt1.Text);
  MyFigure.SeiteB:=StrToInt(edt2.text);
  lbl2.Caption:=FloatToStr(MyFigure.Umfangber);
  lbl3.Caption:=FloatToStr(MyFigure.Flaechenber);
  except
    on E:Exception do
    begin
       ShowMessage('Exception class name = '+E.ClassName);
       ShowMessage('Exception message = '+E.Message);
    end;
  end;
end;

procedure TForm1.btn3Click(Sender: TObject);
var MyFigure: TDreieck;
begin
  MyFigure:=TDreieck.Create;
  try
  MyFigure.SeiteA:=StrToFloat(edt1.Text);
  MyFigure.SeiteB:=StrToFloat(edt2.text);
  MyFigure.SeiteC:=StrToFloat(edt4.text);
  lbl2.Caption:=FloatToStr(MyFigure.Umfangber);
  lbl3.Caption:=FloatToStr(MyFigure.Flaechenber);
  except
    on E:Exception do
    begin
       ShowMessage('Exception class name = '+E.ClassName);
       ShowMessage('Exception message = '+E.Message);
    end;
  end;
end;

procedure TForm1.btn4Click(Sender: TObject);
var MyFigure: TTrapez;
begin
  MyFigure:=TTrapez.Create;
  try
  MyFigure.SeiteA:=StrToFloat(edt1.Text);
  MyFigure.SeiteB:=StrToFloat(edt2.text);
  MyFigure.Hoehe:=StrToFloat(edt3.text);
  MyFigure.SeiteC:=StrtoFloat(edt4.Text);
  MyFigure.SeiteD:=StrtoFloat(edt5.Text);
  lbl2.Caption:=FloatToStr(MyFigure.Umfangber);
  lbl3.Caption:=FloatToStr(MyFigure.Flaechenber);
  except
    on E:Exception do
    begin
       ShowMessage('Exception class name = '+E.ClassName);
       ShowMessage('Exception message = '+E.Message);
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  edt1.Clear;
  edt2.Clear;
  edt3.Clear;
  edt4.Clear;
  edt5.Clear;
  lbl2.Caption:='';
  lbl3.Caption:='';
end;

end.
Norbert
  Mit Zitat antworten Zitat
Rudy Velthuis

Registriert seit: 10. Sep 2011
Ort: Gelsenkirchen
42 Beiträge
 
Delphi 10.3 Rio
 
#9

AW: Interface richtig verstanden?

  Alt 4. Mai 2019, 15:10
Nun möchte ich noch etwas tiefer in die Problematik Interface einsteigen.
Interfaces sind keine Problematik, sie sind eine Lösung.
Rudy Velthuis
  Mit Zitat antworten Zitat
EdAdvokat

Registriert seit: 1. Mai 2016
Ort: Berlin
414 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#10

AW: Interface richtig verstanden?

  Alt 4. Mai 2019, 16:15
Hallo zusammen,
nun habe ich mit meiner Drohung ernst gemacht und biete eine neue "Lösung" der Problematik (!) Interface an.
Um nicht auch eines Plagiats verdächtig zu sein verweise ich auf eine 3-teilige Videoaufzeichnung von StahliSoft in seinem Youtubekanal zu diesem Thema.
Ich habe diese Videos aufmerksam verfolgt und mit dem beiliegenden Projekt nachempfunden. Ich danke dem Euch sicher aus dem hiesigen Formum und seinen
anderen Veröffentlichungen bekannten A. Stahl ganz herzlich für das sehr unaufgeregt und verständlich dargestellte Video zu einem doch nicht ganz einfachen Thema.
Ich hoffe, dass ich alles richtig gemacht habe. Jedenfalls läuft es bei mir ohne erkenntliche Fehler.
Angehängte Dateien
Dateityp: zip Interface_new1.zip (54,7 KB, 6x aufgerufen)
Norbert

Geändert von EdAdvokat ( 4. Mai 2019 um 16:23 Uhr)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 21:32 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz