AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Verständnisfrage: Interface und dazugehöriges Objekt
Thema durchsuchen
Ansicht
Themen-Optionen

Verständnisfrage: Interface und dazugehöriges Objekt

Ein Thema von TiGü · begonnen am 23. Aug 2012 · letzter Beitrag vom 23. Aug 2012
Antwort Antwort
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.070 Beiträge
 
Delphi 10.4 Sydney
 
#1

Verständnisfrage: Interface und dazugehöriges Objekt

  Alt 23. Aug 2012, 16:51
Delphi-Version: 2009
Bin gerade über alten Code gestoßen und bin mir unsicher, ob das so sein darf:
Delphi-Quellcode:
class function TContainer.CreateContainer(...) : IContainer;
var BlaType : IBlaType;
    Example : TContainer; //IContainer;
begin
  Result := nil;
  Example := TContainer.Create(...);
  if Assigned(Example) and FindBlaType(...) then
  begin
    Example.SetIrgendwas(BlaType);
    Result := Example;
  end;
end;
In dem vereinfachten und gekürzten Beispiel muss noch die Variable Example von Typ IContainer sein, so wie im Kommentar angedeutet, oder etwas nicht?
Hab ich hier den Fall vorliegen, vor dem immer gewarnt wird?
"Du sollst nicht Interface- und Objekt-Referenzen mischen!"
  Mit Zitat antworten Zitat
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#2

AW: Verständnisfrage: Interface und dazugehöriges Objekt

  Alt 23. Aug 2012, 17:09
Solltest du wahrlich machen. Sonst bekommst ein Problem mit der autom. Referenzzählung!

Zitat:
Hab ich hier den Fall vorliegen, vor dem immer gewarnt wird?
"Du sollst nicht Interface- und Objekt-Referenzen mischen!"
Jup, hast du!

Wobei ich den Code eh nicht ganz verstehe, wenn ich ehrlich bin... Wieso sollte Assigned nach dem Create jemals False liefern? Create ist schon ein Konstruktor? Diese Methode würde in der aktuellen Version eh niemals nil liefern. In so fern Create eine Exception wirft, wird diese ja nicht abgefangen -- außer du hast natürlich diesen Code entfernt
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#3

AW: Verständnisfrage: Interface und dazugehöriges Objekt

  Alt 23. Aug 2012, 17:11
In dem gezeigten Code ist es so, daß hier nicht beide Referenzen "gleichzeitig" verwendet werden.
(oftmals macht man sowas, wenn auf eine Funktion des Objekts zugreifen will, welche man "vergessen" hat ins Interface aufzunehmen)

Objekt vor Interface funktioniert oftmals noch.
Example := TContainer.Create(...); => Selbst wenn hier Example ein IContainer wäre, würde es kurz vor der Zuweisung noch als Objekt behandelt.

Es kommt jetzt allerdings noch drauf an, was FindBlaType(...) und SetIrgendwas macht und ob darin eine Interfacereferenz dieses Objekts erzeugt/verwendet wird, denn dann hat man mit diesem Vorgehen ein Problem, da man dann Interface- und Objektreferenz gleichzeitig verwendet.

Objekt nach Interface ist standardmäig nicht möglich, da man hierfür, bei Freigabe der letzen Interfacereferenz, die Freigabeautomatik des Interfaces deaktivieren müßte.
Bzw. man muß an den Stellen, wo man es in als Objekt benötigt, sicherstellen, daß über diese Dauer immer mindestens eine Interfacereferenz existiert.


Außerdem gibt es hier ein Speicherleck, wenn das IF ein False liefert, bzw. wenn es eine Exception gibt ... also wenn der Programmablauf nicht beim Result := vorbei kommt, da sich dann niemand dafür verantwortlich hält, dieses Objekt wieder freizugeben.
$2B or not $2B

Geändert von himitsu (23. Aug 2012 um 17:19 Uhr)
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#4

AW: Verständnisfrage: Interface und dazugehöriges Objekt

  Alt 23. Aug 2012, 17:41
So wäre es richtig:
Delphi-Quellcode:
class function TContainer.CreateContainer(...) : IContainer;
var BlaType : IBlaType;
begin
  Result := TContainer.Create(...);
  if FindBlaType(...) then
  begin
    Example.SetIrgendwas(BlaType);
  end
  else
    Result := nil;
end;
Andreas
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.070 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: Verständnisfrage: Interface und dazugehöriges Objekt

  Alt 23. Aug 2012, 17:53
Also so sieht es eigentlich aus, musste aber Firmenspezifische Abkürzungen von ein paar Bezeichnern entfernen.
Die Kommentare sind von mir für euch zur Erklärung!

Delphi-Quellcode:
class function TNotifyEventContainer.CreateContainer(ANotification : HNotification; AExtMedium : IAExtMedium) : IEventContainer;
var
  EventType : IEventType;
  Event : TNotifyEventContainer; //IEventContainer;
begin
  Result := nil;
  if Assigned(AExtMedium) then
  begin
    //in diesem Create steckt ein "leeres" Try-Except mit nur OutputDebugString um den Konstruktur-Code
    Event := TNotifyEventContainer.Create(ANotification, AExtMedium.GetAliasName, AExtMedium.GetGuid);    
   
   //FindEventType ist eine flache Funktion in der Unit.
   //GetEventTypes liefert eine IInterfaceList.
   //EventType ist ein out-Parameter, die Funktion sucht in der Liste anhand
   //von GetEventTypeID das betreffende IEventType in der IInterfaceList und gibt es zurück
    if Assigned(Event) and FindEventType(AExtMedium.GetEventTypes, Event.GetEventTypeID, EventType) then
    begin
      //setzt nur EventType als Field-Variable von TNotifyEventContainer
     Event.SetEventType(EventType);    
    end;
 
    Result := Event;
  end;
end;
Zur meiner Verteidigung muss ich sagen, dass das nicht von mir, sondern von meinen Vorgänger stammt.
Ich wäre hierrüber auch nie gestoßen, hätte ich nicht manchmal merkwürdige Effekte/Fehlermeldungen, seitdem ich FastMM4 installiert habe.
Der alte Speichermanager hatte wahrscheinlich beide Augen zugedrückt.

Geändert von TiGü (23. Aug 2012 um 18:02 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.070 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Verständnisfrage: Interface und dazugehöriges Objekt

  Alt 23. Aug 2012, 18:01
Wobei ich den Code eh nicht ganz verstehe, wenn ich ehrlich bin... Wieso sollte Assigned nach dem Create jemals False liefern?
Siehe neues Beispiel!

Zitat:
Create ist schon ein Konstruktor?
In so fern Create eine Exception wirft, wird diese ja nicht abgefangen -- außer du hast natürlich diesen Code entfernt
Ja, ein normaler constructor Create;

Es kann schon passieren, dass beim Erstellen der Klasse irgendwas schiefgeht.
Darum hat mein Vorgänger um den Code im Create ein leeres try-except gestrickt.
Wenn es nun dadrin zur einer Exception kommt, dann existiert Example/Event nicht und jeder Zugriff drauf würde doch mit einer AV enden, oder?
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.070 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: Verständnisfrage: Interface und dazugehöriges Objekt

  Alt 23. Aug 2012, 18:10
In dem gezeigten Code ist es so, daß hier nicht beide Referenzen "gleichzeitig" verwendet werden.
(oftmals macht man sowas, wenn auf eine Funktion des Objekts zugreifen will, welche man "vergessen" hat ins Interface aufzunehmen)
Dafür wird im betreffenden Projekt gerne das gemacht.
Wobei ich dabei auch immer irgendwie Bauchschmerzen habe.

Delphi-Quellcode:
TMyClass = class;

IMyInterface
  function GetObject : TMyClass;
end;

TMyClass = class(TInterfacedObject, IMyInterface)
  function GetObject : TMyClass;
end

...

function TMyClass.GetObject : TMyClass;
begin
 Result := self;
end;
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#8

AW: Verständnisfrage: Interface und dazugehöriges Objekt

  Alt 23. Aug 2012, 18:19
:gelöscht:
$2B or not $2B

Geändert von himitsu (23. Aug 2012 um 18:40 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#9

AW: Verständnisfrage: Interface und dazugehöriges Objekt

  Alt 23. Aug 2012, 18:39
Wenn etwas im Constructor schief geht, dann maximal eine Exception.

Also entweder wird der Constructor ausgeführt (keine Exception) und die Variable wird zugewiesen,
oder es knallt mit einer Exception raus, der variable wird nix zugewiesen, aber auch der nachfolgende Code wird nicht mehr ausgeführt.

Wenn das Programm zum IF kommt, sollte es immer etwas drinsteht, also niemals nil.
(es sei denn jemand überschreibt TObject.NewInstance und gibt dort bösartiger Weise NIL zurück, aber das ist soein Fall, den braucht man nicht beachten, denn wer sowas tut, der soll sich nicht wundern, wenn es dann wo anders knallt)

Delphi-Quellcode:
type
  TMyObject = class
    constructor Create;
  end;

constructor TMyObject.Create;
begin
  Abort; // raise Exception.Create('peng');
end;

var
  O: TObject;
begin
  O := TMyObject.Create;
  if Assigned(O) then
    ShowMessage('OK')
  else
    ShowMessage('nil'); // das sieht man niemals
Zitat:
Dafür wird im betreffenden Projekt gerne das gemacht.
Wobei ich dabei auch immer irgendwie Bauchschmerzen habe.
Das mit dem GetObject ist in aktuelleren Delphis schon enthalten.

Nur sieht man dort dieses "Interface" nicht direkt, da es kein echtes Interface ist, sondern eine statische GUID, welche im AS-Operator wie ein virtuelles Interface behandelt wird.
Delphi-Quellcode:
var
  i: IMyInterface;
  o: TMyObject;

o := i as TMyObject;
Delphi-Quellcode:
type
  IMyInterface = interface
    ['{C6936E1B-F0FE-42A0-A00E-39E90A66A9F0}']
    procedure Test;
  end;

  TMyObject = class(TInterfacedObject, IMyInterface)
    FText: string;
    constructor Create;
    procedure Test;
  end;

procedure TMyObject.Test;
begin
  ShowMessage(FText);
end;

constructor TMyObject.Create;
begin
  inherited;
  FText := 'Hallo Welt.';
end;

procedure TForm10.Button3Click(Sender: TObject);
var
  I: IMyInterface;
  O: TMyObject;
begin
  I := TMyObject.Create;
  O := I as TMyObject;
  O.Test;
  I := nil; // letzte und einzige Interfacereferenz vernichten
  O.Test;
end;
Aber wie gesagt, man muß wärend man auf dieses Objekt zugreift unbedingt verhindern, daß der Referenzzähler auf 0 geht, jedenfalls bei Interfaces welche sich über die Referenzzählung verwaltet werden.
Bei Onterfaces wo die Freigabe anders gesteuert wird, muß mn eben aufpassen, daß dieses ebenfalls nicht freigegeben wird.

PS: TComponent enthalten Interfaces, welche sich nicht selber freigeben.
Die Freigabe geschieht dort ausschließtlich über das Objekt (Free) und dem Free ist es egal, ob es irgendwo noch Referenzen auf dieses Interfaces/Objekt gibt.
$2B or not $2B

Geändert von himitsu (23. Aug 2012 um 18:43 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


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 09:44 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