Explizit Ausdruck der Eigentümerschaft in Delphi

8

Ich bin hauptsächlich ein C ++ - Programmierer, und ich habe mich daran gewöhnt, Klassenvorlagen wie std::unique_ptr , std::shared_ptr usw. zu haben, um den Besitz meiner Objekte auszudrücken. Hat Delphi etwas, das in seiner Standardbibliothek ähnlich ist? Gibt es Best Practices für das Ausdrücken von Objektbesitzern, denen ich folgen sollte, während ich meinen Code schreibe?

Bearbeiten: Da C ++ 11 zum Standard wurde, gibt es zwei einfache Hilfsklassen, std::shared_ptr und std::unique_ptr .

Wenn ich eine Variable vom Typ std::shared_ptr<int> erzeuge, stellt sie einen Zeiger auf ein int mit gemeinsamem Besitz dar: Unter der Haube wird eine Referenz gezählt, und wenn die ref-Zählung Null erreicht, wird der Zeiger automatisch freigegeben. Dieser Typ drückt eine Art "geteilter Besitz" aus, bei dem viele Objekte die Verantwortung teilen, die Ressource zu zerstören, wenn sie damit fertig sind.

Im Gegensatz dazu drückt std::unique_ptr eine einzelne Eigentümerschaft aus. Wenn der Wert für unique_ptr den Gültigkeitsbereich verlässt, wird die Ressource automatisch freigegeben. std :: unique_ptr kann nicht kopiert werden: Es kann genau ein Objekt geben, das diese Ressource gleichzeitig besitzt, und genau ein Objekt ist dafür verantwortlich, das Objekt zu bereinigen.

Vergleichen Sie diese Lightweight-Klassen mit einem nackten Zeiger auf int, wo sie entweder den gemeinsamen Besitz, den eindeutigen Besitz oder nur einen Verweis auf ein anderes Objekt darstellen können! Der Typ sagt nichts.

Meine Frage ist: Wie Delphi unterstützt, Referenzen auf Objekte zu halten, gibt es Mechanismen, explizit zu sagen: "Ich bin der alleinige Besitzer dieses Objekts, wenn ich damit fertig bin, werde ich es befreien", vs "Ich bin Ich behalte nur einen Verweis auf dieses Objekt herum, um mit ihm zu interagieren, aber jemand anderes wird es aufräumen. "vs" Ich teile dieses Objekt mit vielen anderen Objekten, und wer immer es zuletzt hat, wird es aufräumen. "

Ich weiß, dass Collections.Generics verschiedene Sammlungen wie TList vs TObjectList hat, wobei TObjectList die darin gespeicherten Mitglieder freigibt, TList aber nicht. Sie können sagen, dass TObjectList seine Elemente "besitzt", während TList dies nicht tut. Das ist die Essenz meiner Frage, wirklich. Gibt es bei der Gestaltung meiner eigenen Kurse Möglichkeiten, solche Eigentumsfragen direkt in der Sprache auszudrücken? Oder gibt es Best Practices / Namenskonventionen, die unter Entwicklern üblich sind?

    
bstamour 12.09.2013, 12:43
quelle

3 Antworten

4

Ich kenne keine Sprachkonstrukte, die helfen können, noch irgendwelche "Standardbenennungskonventionen".

Vor langer Zeit habe ich jedoch die folgende Namenskonvention übernommen, um leichter überprüfen zu können, ob Klassen sauber hinter sich selbst bereinigen:

  • Gemäß der Standard-Delphi-Konvention beginnen alle Feldnamen mit einem "F".
  • Objektreferenzen, für die die Klasse die Verantwortung für die Lebenszeitverwaltung hat / übernimmt, beginnen Sie mit "FMy".
  • Interface-Referenzen, die die Klasse explizit freigeben sollte, indem der Verweis auf nil im Destruktor gesetzt wird (für die Performance, um eine zyklische Abhängigkeit zu brechen usw.), beginnen Sie mit "FMi"

Sehr grob, aber es funktioniert, und hat viel geholfen, wenn man Code durchgeht, den man seit einiger Zeit nicht mehr gesehen hat, um diese zu verhindern. "Warte, sollte diese Referenz nicht freigegeben oder vernichtet werden?" Suchen.

    
Marjan Venema 12.09.2013, 18:07
quelle
2
  

std :: unique_ptr kann nicht kopiert werden: Es kann genau ein Objekt geben, das diese Ressource gleichzeitig besitzt

In der Delphi-Sprache gibt es weder einen Typ noch einen Mechanismus, der verhindert, dass "Eigentümer" freigegeben wird. Eine Kopie jeder Referenz kann immer gemacht werden. (Lies: In Delphi gibt es nichts, was dir erlaubt, die Zuordnung zu blockieren, wie David . David schön ausgedrückt.)

  

Wenn unique_ptr den Gültigkeitsbereich verlässt, wird die Ressource automatisch freigegeben.

In Delphi ist dies nur mit (oder über) Schnittstellen möglich. Delphi hat keinen Garbage Collector.

  

Und es gibt genau ein Objekt, das dafür verantwortlich ist, das Objekt zu reinigen.

Verantwortung für die Reinigung müssen Sie selbst erzwingen. Oder delegieren Sie diese Aufgabe an ein (anderes) Framework. Zum Beispiel implementiert die Delphi-VCL-Standardklasse TComponent automatisches Eigentum (und Zerstörung), das optional mit RemoveComponent und InsertComponent ausgetauscht / kontrolliert werden kann.

  

Gibt es bei der Gestaltung meiner eigenen Klassen Möglichkeiten, solche Eigentumsfragen direkt in der Sprache auszudrücken? Oder gibt es Best Practices / Namenskonventionen, die unter Entwicklern üblich sind?

Nicht genau zum Thema, aber sicher verwandt: Es gibt mehrere Singleton-Entwurfsmusterimplementierungen, die das einmalige Erstellen von Objekten erzwingen.

Bezüglich Namenskonventionen: Der Begriff "Owner" (oder "OwnsObjects" aus Ihrem eigenen Beispiel) drückt definitiv das Eigentum in dem Sinne aus, dass dieser Besitzer bei Bedarf für die Vernichtung sorgt. Daher benötigt eine Schaltfläche, die mit einem Formular als Eigentümer erstellt wurde (der einzige Parameter des Standardkonstruktors der Schaltfläche) keine manuelle Zerstörung.

    
NGLN 12.09.2013 18:01
quelle
1

Die Konzepte in Delphi unterscheiden sich in vielen Fällen von C ++. Beide Sprachen sind dritte Generation, aber Delphi arbeitet gerne auf einer höheren Abstraktionsebene als C ++. Zum Beispiel unterstützt Delphi Zeiger, aber sie werden nur selten verwendet, wenn sie mit dem Referenzbegriff zusammenhängen, der nicht genau derselbe ist wie in C ++.

In Delphi sind Objektvariablen tatsächlich Referenzen (oder auf einer niedrigeren Abstraktionsebene sind sie Zeiger). In C ++, wenn Sie eine Objektvariable deklarieren, wird der Konstruktor sofort aufgerufen, in Delphi ist es nicht und Sie müssen es in einem bestimmten Moment aufrufen, was Speicher zuweisen und den Konstruktor ausführen wird. So wird die Speicherverwaltung von Objekten in C ++ und Delphi auf unterschiedliche Lebenszyklen konditioniert.

All dies wurde nur gesagt, um Ihnen zu sagen, dass der Design-Stil des Speichermanagements in Delphi anders ist als in C ++. Deshalb hat Delphi keine Helferklasse, die genau das tut, was Sie wollen. Delphi bietet jedoch ein Konzept namens Interfaces , das in C ++ nicht existiert (zumindest nicht, als ich vor Jahren mit C ++ gearbeitet habe). Schnittstellen sind einer abstrakten Klasse in dem Sinne ähnlich, dass sie keinen Code haben. Sie müssen einer Schnittstelle einen Klassenimplementierer bereitstellen, und diese Klasse stellt den Code bereit. % Co_de% bietet jedoch eine Speicherverwaltung für die Referenzzählung, von der ich glaube, dass sie genau Ihren Anforderungen entspricht.

Also, meine Antwort an Sie lautet: Das engste Sprachkonstrukt, das Delphi Ihnen hinsichtlich der Speicherverwaltung bietet, die Sie für Ihre Zwecke verwenden können, ist Schnittstellen . Also schlage ich vor, dass Sie es mindestens ein bisschen studieren, um Ihre eigenen Schlüsse zu ziehen.

    
AlexSC 12.09.2013 18:50
quelle