AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Tutorials Interfaces + Factorys

Interfaces + Factorys

Ein Tutorial von stahli · begonnen am 29. Jan 2015 · letzter Beitrag vom 22. Feb 2015
Antwort Antwort
Seite 3 von 7     123 45     Letzte » 
Benutzerbild von stahli
stahli
Registriert seit: 26. Nov 2003
Ich habe länger gebraucht, um das Konzept und die Benutzung von Interfaces in Delphi zu verstehen.

Es gibt zwar einige Erklärungen und Beispiele, die waren jedoch nicht immer für Neulinge in dem Themenbereich geeignet.

Daher habe ich hier einmal versucht, meine Erkenntnisse und bisherigen Erfahrungen zusammenzufassen.
Die Videos sind nicht hochprofessionell, aber vielleicht helfen sie einigen Interessierten, die Interfaces in Delphi schneller zu verstehen und anwenden zu können...


Die Erläuterungen habe ich in 3 Blöcke aufgeteilt:

Einige Basics zu Interfaces in Delphi.
http://youtu.be/MEX1836SvgE

Etwas detaillierte Infos und Anwendungsbeispiele.
http://youtu.be/IyvqZAUSJGY

Verbergen der Klassen und Arbeiten nur mit Interfaces.
http://youtu.be/NcbIV0SUFJs


Wenn ich etwas fehlerhaft oder unvollständig erläutert habe, dann können wir das hier gern richtig stellen...
Angehängte Dateien
Dateityp: zip Interfaces_Factory.zip (89,1 KB, 71x aufgerufen)
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
 
Benutzerbild von Sir Rufo
Sir Rufo

 
Delphi 10 Seattle Enterprise
 
#21
  Alt 31. Jan 2015, 16:05
IIRC stimmt das so nicht ganz. Wenn man das Interface nutzt, zeigt zwar die Codevervollständigung Getter und Setter nicht an, sie lassen sich aber trotzdem direkt aufrufen. Das ist zwar Quark, aber wohl nicht zu ändern.
Und was ist technisch gesehen der Unterschied zwischen dem impliziten und expliziten Aufruf von Getter und Setter?

Aus welchen technischen Gründen werden bei Klassen die Getter/Setter idR nicht public deklariert?
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

 
Delphi 11 Alexandria
 
#22
  Alt 31. Jan 2015, 16:24
Technisch gesehen ist das natürlich gleich.
Aber wenn man sich erst neu mit Interfaces befasst kann halt etwas undurchsichtig sein und Einsteiger verstehen die Zusammenhänge nicht direkt.

Wenn man erst mal verstanden hat wie es läuft, dann kommt man damit allerdings zurecht - geht jedenfalls mir so.
Jedenfalls weiß ich jetzt, dass ich Getter und Setter deklarieren muss, mir die Codevervollständigung diese aber nicht andauernd unter die Nase reibt wenn sie privat sind.

Damit kann ich leben.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

 
Delphi 10 Seattle Enterprise
 
#23
  Alt 31. Jan 2015, 16:28
Das mit dem Getter/Setter muss ich doch schon ohne Interfaces verstanden haben und warum diese idR nicht als public deklariert werden. Dann versteht man auch warum es schnurz ist, wenn man doch darauf zugreifen kann (weil das technisch bedingt bei Interfaces so ist und nicht anders möglich ist).
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

 
Delphi 11 Alexandria
 
#24
  Alt 31. Jan 2015, 16:28
Wofür braucht man technisch gesehen überhaupt Sichtbarkeiten?
Detlef
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

 
Delphi 10 Seattle Enterprise
 
#25
  Alt 31. Jan 2015, 16:30
Wofür braucht man technisch gesehen überhaupt Sichtbarkeiten?
Bei einer public Property werden die Getter/Setter nur aus kosmetischen Gründen nicht public deklariert, eben aus dem gleichen Grund warum die Codevervollständigung bei Interfaces die Getter/Setter nicht anzeigt.
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

 
Delphi 11 Alexandria
 
#26
  Alt 1. Feb 2015, 12:00
Jetzt muss ich noch etwas zum Video 2 + 3 nachfragen (Stand hochgeladenes Projekt vom ersten Beitrag).

Ich habe zwei Fahrzeuge, die einen Motor haben (Auto und Boot).
Jetzt könnte man sich noch ein Elektrofahrrad einführen, hätte also 3 Klassen mit einem Motor.

Wenn IMotor StarteMotor und Tanken implementiert, müssen das die 3 Klassen auch unmittelbar tun.
Auto und Boot könnten aber mit einem Benzin-, Diesel- oder Elektromotor ausgestattet werden.

Wäre es somit nicht vielleicht sinnvoll, eine Klasse TMotor UND dazugehörige Schnittstelle IMotor einzuführen?

Dann könnten die Fahrzeuge so aussehen:

Bsp. Auto:
Delphi-Quellcode:
  TAuto = class(TInterfacedObject, IHasMotor)
  private
    FMotor: IMotor;
      FAnzahlRaeder: Integer;
      procedure SetAnzahlRaeder(const Value: Integer);
      procedure Fahre;
    //procedure StarteMotor;
    //procedure Tanken;
  public
    property Motor: IMotor read get_Motor write set_Motor;
      property AnzahlRaeder: Integer read FAnzahlRaeder write SetAnzahlRaeder;
  end;
Die Interfaces könnten dann so aussehen:

Delphi-Quellcode:
  IMotor = interface
    procedure StarteMotor;
    procedure Tanken;
  end;

  IHasMotor = interface
    function get_Motor: IMotor;
    procedure set_Motor(const Value: IMotor);
    property Motor: IMotor read get_Motor write set_Motor;
  end;
So könnte man dem Auto verschiedene Motoren hinzufügen.
Allerdings könnte ein Elektromotor dann nicht tanken sondern man würde die Batterie aufladen.
Ich muss also zur Laufzeit ggf. immer prüfen, welcher Motor eingebaut ist und ob überhaupt einer existiert.

Klar, man kann der Fabrik schon sagen: Gib mir ein Auto mit Elektromotor zurück, aber zur Laufzeit weiß man ja dann dennoch nicht, was man nun genau vorliegen hat.

An der Stelle komme ich nicht ganz weiter.
Wie würdet Ihr damit umgehen? (Aber bitte nicht auf das Spring-Framework o.ä. verweisen, damit das hier nachvollziehbar bleibt.)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

 
Delphi 10 Seattle Enterprise
 
#27
  Alt 1. Feb 2015, 12:14
Mal ganz weg von der Programmierung, aber das Betanken an und für sich im Sinne von "fülle das nach, damit der Motor arbeiten kann" ist doch für jeden Motor in diesem Sinne gleich.

Das was man tankt muss zum Motor passen, aber "Tanken" müssen sie alle (vor allem weil "Tanken" das Befüllen eines "Tanks" -> Vorratsbehälters beschreibt ohne dabei das Tankgut oder den Tank irgendwie einzuschränken).

Also ist Tanken als Methode völlig ok (wenn das, was man tankt in diesem Kontext keine Rolle spielt bzw. spielen muss).

Einen konkreten Dieselmotor würde man dann mit einer Verbindung zu einem Diesel-Lieferanten erzeugen, den Benzinmotor mit einer Verbindung zu einem Benzin-Lieferanten und den Elektromotor mit einem Strom-Lieferanten.
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

 
Delphi 11 Alexandria
 
#28
  Alt 1. Feb 2015, 12:33
Den Unterschied zwischen Tanken und Aufladen habe ich nur exemplarisch ins Spiel gebracht.
Es kann ja in echten Fällen möglicherweise Unterschiede geben, die für den weiteren Verlauf relevant sind.

Das ERZEUGEN eines Autos mit einem bestimmten Motor sehe ich nicht als Problem.
Aber später müsste ich immer prüfen:
- Kann das Objekt, das ich hier habe einem Motor haben?
- Hat es tatsächlich einen Motor?
- Kann ich damit tanken und was oder an die Steckdose?

Würdest Du also meine zwei Schnittstellen IMotor (die dann eine tatsächliche Motorinstanz representiert) und eine Schnittstelle IHasMotor (oder eigentlich besser: IKannMotorHaben) (die einem Auto und Boot hinzugefügt wird, nicht aber einem Fahrrad oder Vogel) sinnvoll finden?
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

 
Delphi 10 Seattle Enterprise
 
#29
  Alt 1. Feb 2015, 12:33
Man kann das mit dem Motor auch anders darstellen
Delphi-Quellcode:
IBetriebsstoffQuelle = interface
  function GetBetriebsstoffArt : Integer;
  procedure Entnehme( AMenge : Single );
end;

IMotor = interface
  procedure Tanken( AQuelle : IBetriebsstoffQuelle );
end;
Jetzt kann der Motor prüfen, ob die Quelle den richtigen Betriebsstoff liefert und sich die benötigte Menge entnehmen.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

 
Delphi 10 Seattle Enterprise
 
#30
  Alt 1. Feb 2015, 12:44
Den Unterschied zwischen Tanken und Aufladen habe ich nur exemplarisch ins Spiel gebracht.
Es kann ja in echten Fällen möglicherweise Unterschiede geben, die für den weiteren Verlauf relevant sind.

Das ERZEUGEN eines Autos mit einem bestimmten Motor sehe ich nicht als Problem.
Aber später müsste ich immer prüfen:
- Kann das Objekt, das ich hier habe einem Motor haben?
- Hat es tatsächlich einen Motor?
- Kann ich damit tanken und was oder an die Steckdose?

Würdest Du also meine zwei Schnittstellen IMotor (die dann eine tatsächliche Motorinstanz representiert) und eine Schnittstelle IHasMotor (oder eigentlich besser: IKannMotorHaben) (die einem Auto und Boot hinzugefügt wird, nicht aber einem Fahrrad oder Vogel) sinnvoll finden?
Das ist immer genau das Problem an diesen "an den Haaren herbeigezogenen" Beispielen, wo man Enten, Fahrräder und Autos irgendwie gleich behandeln will. Man kommt nicht so richtig ins vorne und stösst dabei auch eben auf die besagten Probleme.

Sinnvoller erscheint mir etwas wie
Delphi-Quellcode:
IMotorBetrieben = interface
  funtion GetMotor : IMotor;
end;

IMobil = interface
  procedure BewegeZu( Ort : TPoint );
end;

IKannSprechen = interface
  procedure Sage( AText : string );
end;
Mit Supports fragt man dann ab, ob dieses oder jenes Interface unterstützt wird und führt das dann aus:
Delphi-Quellcode:
procedure Sage( AText : string; AContext : IInterface );
var
  LSprecher : IKannSprechen;
begin
  if Supports( AContext, IKannSprechen, LSprecher ) then
    LSprecher.Sage( AText );
end;
  Mit Zitat antworten Zitat
Themen-Optionen Tutorial durchsuchen
Tutorial 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 13:24 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