{"id":312,"date":"2023-05-01T08:09:00","date_gmt":"2023-05-01T08:09:00","guid":{"rendered":"https:\/\/jorgeturiel.es\/?p=312"},"modified":"2023-08-11T21:11:54","modified_gmt":"2023-08-11T20:11:54","slug":"introduccion-al-lenguaje-pascal-moderno-para-programadores-parte-4","status":"publish","type":"post","link":"https:\/\/jorgeturiel.es\/?p=312","title":{"rendered":"Introducci\u00f3n al lenguaje Pascal moderno para programadores (Parte 4)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\" id=\"block-5521090e-ab25-4c7d-8ff9-7b06a21f4a1b\">Continuamos con la introducci\u00f3n al lenguaje Pascal Moderno.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"block-404f08e6-e309-4eb0-84cf-cdf990136039\">Esta entrada es una traducci\u00f3n al espa\u00f1ol, del texto <a rel=\"noreferrer noopener\" href=\"https:\/\/castle-engine.io\/modern_pascal\" target=\"_blank\">original<\/a> escrito por Michalis Kamburelis.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">Liberando las clases<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Recuerde liberar todas las instancias de las clases<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Las instancias de clase deben liberarse manualmente, de lo contrario, se producen p\u00e9rdidas de memoria. Recomiendo usar las opciones FPC -gl -gh para detectar fugas de memoria (ver <a rel=\"noreferrer noopener\" href=\"https:\/\/castle-engine.io\/manual_optimization.php#section_memory\" target=\"_blank\">https:\/\/castle-engine.io\/manual_optimization.php#section_memory<\/a>).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Tenga en cuenta que esto no se refiere a las excepciones planteadas. Aunque creas una clase cuando generas una excepci\u00f3n (y es una clase perfectamente normal, y tambi\u00e9n puedes crear tus propias clases para este prop\u00f3sito). Pero esta instancia de clase se libera autom\u00e1ticamente.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u00bfC\u00f3mo liberar?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Para liberar la instancia de clase, es mejor llamar a FreeAndNil(A) desde la unidad SysUtils en su instancia de clase. Comprueba si A es nil, si no, llama a su destructor y establece A en nil. Entonces llamarlo muchas veces seguidas no es un error. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Es m\u00e1s o menos un atajo para<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">if A &lt;&gt; nil then\nbegin\n  A.Destroy;\n  A := nil;\nend;<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">En realidad, eso es una simplificaci\u00f3n excesiva, ya que FreeAndNil hace un truco \u00fatil y establece la variable A en nil antes de llamar al destructor en una referencia adecuada. Esto ayuda a prevenir cierta clase de errores\u2009\u2014\u2009la idea es que el c\u00f3digo \u00abexterno\u00bb nunca deber\u00eda acceder a una instancia de la clase medio destruida.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A menudo, tambi\u00e9n ver\u00e1 personas que usan el m\u00e9todo A.Free, que es como hacer<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">if A &lt;&gt; nil then\n  A.Destroy;<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Esto libera la A, a menos que sea nula. Tenga en cuenta que, en circunstancias normales, nunca debe llamar a un m\u00e9todo en una instancia que puede ser nula. Entonces, la llamada <em>A.Free<\/em> puede parecer sospechosa a primera vista, si A puede ser nula. Sin embargo, el m\u00e9todo gratuito es una excepci\u00f3n a esta regla. Hace algo sucio en la implementaci\u00f3n, es decir, comprueba si <em>Self &lt;&gt; nil.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nota: Este truco sucio (permitir oficialmente que el m\u00e9todo se use con Self equal nil) solo es posible para m\u00e9todos no virtuales. Y siempre que Self = nil sea posible, el m\u00e9todo no puede llamar a ning\u00fan m\u00e9todo virtual ni acceder a ning\u00fan campo, ya que estos se bloquear\u00edan con una violaci\u00f3n de acceso cuando se llamaran en un puntero nulo. Consulte el c\u00f3digo de ejemplo method_with_self_nil.lpr. No recomendamos usar este truco en su propio c\u00f3digo (para m\u00e9todos virtuales o no virtuales), ya que es contrario a la intuici\u00f3n del uso normal; en general, todos los m\u00e9todos de instancia deber\u00edan poder asumir que funcionan en una instancia v\u00e1lida (no nula). y puede acceder a los campos y llamar a cualquier otro m\u00e9todo (virtual o no).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Aconsejo usar<em> FreeAndNil(A) <\/em>siempre, sin excepciones, y nunca llamar directamente al m\u00e9todo <em>Free<\/em> o <em>Destroy<\/em> destructor. Castle Game Engine lo hace as\u00ed. Ayuda mantener una buena afirmaci\u00f3n de que todas las referencias son nulas o apuntan a instancias v\u00e1lidas.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Liberaci\u00f3n manual y autom\u00e1tica<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">En muchas situaciones, la necesidad de liberar la instancia no es un gran problema. Simplemente escribe un destructor, que coincide con un constructor, y desasigna todo lo que se asign\u00f3 en el constructor (o, m\u00e1s completamente, en toda la vida \u00fatil de la clase). Tenga cuidado de liberar cada cosa solo una vez. Por lo general, es una buena idea establecer la referencia liberada en cero, por lo general, es m\u00e1s c\u00f3modo hacerlo llamando a FreeAndNil (A).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Entonces, as\u00ed:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">uses SysUtils;\n\ntype\n  TGun = class\n  end;\n\n  TPlayer = class\n    Gun1, Gun2: TGun;\n    constructor Create;\n    destructor Destroy; override;\n  end;\n\nconstructor TPlayer.Create;\nbegin\n  inherited;\n  Gun1 := TGun.Create;\n  Gun2 := TGun.Create;\nend;\n\ndestructor TPlayer.Destroy;\nbegin\n  FreeAndNil(Gun1);\n  FreeAndNil(Gun2);\n  inherited;\nend;<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Para evitar la necesidad de liberar expl\u00edcitamente la instancia, tambi\u00e9n se puede usar la funci\u00f3n TComponent de \u00abpropiedad\u00bb. Un objeto que es propiedad ser\u00e1 liberado autom\u00e1ticamente por el propietario. El mecanismo es inteligente y nunca liberar\u00e1 una instancia ya liberada (por lo que las cosas tambi\u00e9n funcionar\u00e1n correctamente si libera manualmente el objeto que posee antes). Podemos cambiar el ejemplo anterior por este:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \">uses SysUtils, Classes;\n\ntype\n  TGun = class(TComponent)\n  end;\n\n  TPlayer = class(TComponent)\n    Gun1, Gun2: TGun;\n    constructor Create(AOwner: TComponent); override;\n  end;\n\nconstructor TPlayer.Create(AOwner: TComponent);\nbegin\n  inherited;\n  Gun1 := TGun.Create(Self);\n  Gun2 := TGun.Create(Self);\nend;<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Tenga en cuenta que necesitamos anular un constructor virtual de TComponent aqu\u00ed. Entonces no podemos cambiar los par\u00e1metros del constructor. (En realidad, puede\u2009\u2014\u2009declarar un nuevo constructor con reintroduce. Pero tenga cuidado, ya que algunas funcionalidades, por ejemplo, la transmisi\u00f3n, a\u00fan usar\u00e1n el constructor virtual, as\u00ed que aseg\u00farese de que funcione correctamente en cualquier caso).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Tenga en cuenta que siempre puede usar un valor nulo para el propietario. De esta forma, el mecanismo de \u00abpropiedad\u00bb no se utilizar\u00e1 para este componente. Tiene sentido si necesita usar el descendiente de TComponent, pero siempre desea liberarlo manualmente. Para ello, crear\u00eda un componente descendiente como este: ManualGun := TGun.Create(nil);.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Otro mecanismo para la liberaci\u00f3n autom\u00e1tica es la funcionalidad OwnsObjects (\u00a1por defecto ya es cierto!) de clases de lista como TFPGObjectList o TObjectList. Entonces tambi\u00e9n podemos escribir:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">uses SysUtils, Classes, FGL;\n\ntype\n  TGun = class\n  end;\n\n  TGunList = specialize TFPGObjectList&lt;TGun&gt;;\n\n  TPlayer = class\n    Guns: TGunList;\n    Gun1, Gun2: TGun;\n    constructor Create;\n    destructor Destroy; override;\n  end;\n\nconstructor TPlayer.Create;\nbegin\n  inherited;\n  \/\/ Actually, the parameter true (OwnsObjects) is already the default\n  Guns := TGunList.Create(true);\n  Gun1 := TGun.Create;\n  Guns.Add(Gun1);\n  Gun2 := TGun.Create;\n  Guns.Add(Gun2);\nend;\n\ndestructor TPlayer.Destroy;\nbegin\n  { We have to take care to free the list.\n    It will automatically free its contents. }\n  FreeAndNil(Guns);\n\n  { No need to free the Gun1, Gun2 anymore. It's a nice habit to set to \"nil\"\n    their references now, as we know they are freed. In this simple class,\n    with so simple destructor, it's obvious that they cannot be accessed\n    anymore -- but doing this pays off in case of larger and more complicated\n    destructors.\n\n    Alternatively, we could avoid declaring Gun1 and Gun2,\n    and instead use Guns[0] and Guns[1] in own code.\n    Or create a method like Gun1 that returns Guns[0]. }\n  Gun1 := nil;\n  Gun2 := nil;\n  inherited;\nend;<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Tenga en cuenta que el mecanismo de \u00abpropiedad\u00bb de las clases de lista es simple y obtendr\u00e1 un error si libera la instancia utilizando otros medios, mientras que tambi\u00e9n est\u00e1 contenida en una lista. Utilice el m\u00e9todo Extraer para eliminar algo de una lista sin liberarlo, asumiendo as\u00ed la responsabilidad de liberarlo usted mismo.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En Castle Game Engine: Los descendientes de TX3DNode tienen administraci\u00f3n de memoria autom\u00e1tica cuando se insertan como hijos de otro TX3DNode. El nodo ra\u00edz X3D, TX3DRootNode, a su vez, suele ser propiedad de TCastleSceneCore. Algunas otras cosas tambi\u00e9n tienen un mecanismo de propiedad simple: busque par\u00e1metros y propiedades llamados OwnsXxx.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">El destructor virtual llamado Destroy<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Como viste en los ejemplos anteriores, cuando se destruye la clase, se llama a su destructor llamado Destroy.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En teor\u00eda, podr\u00eda tener m\u00faltiples destructores, pero en la pr\u00e1ctica casi nunca es una buena idea. Es mucho m\u00e1s f\u00e1cil tener un solo destructor llamado Destroy, que a su vez es llamado por el m\u00e9todo Free, que a su vez es llamado por el procedimiento FreeAndNil.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">El destructor Destroy en TObject se define como un m\u00e9todo virtual, por lo que siempre debe marcarlo con la palabra clave override en todas sus clases (ya que todas las clases descienden de TObject). Esto hace que el m\u00e9todo Free funcione correctamente. Recuerde c\u00f3mo funcionan los m\u00e9todos virtuales a partir de M\u00e9todos virtuales, anule y vuelva a introducir.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Consejo: Esta informaci\u00f3n sobre los destructores es, de hecho, inconsistente con los constructores.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Es normal que una clase tenga m\u00faltiples constructores. Por lo general, todos se llaman Create y solo tienen diferentes par\u00e1metros, pero tambi\u00e9n est\u00e1 bien inventar otros nombres para los constructores.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Adem\u00e1s, el constructor Create en TObject no es virtual, por lo que no lo marca con anulaci\u00f3n en los descendientes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Todo esto le brinda un poco de flexibilidad adicional al definir constructores. A menudo no es necesario hacerlos virtuales, por lo que, de forma predeterminada, no est\u00e1 obligado a hacerlo.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Tenga en cuenta, sin embargo, que esto cambia para los descendientes de TComponent. El TComponent define un constructor virtual Create(AOwner: TComponent). Necesita un constructor virtual para que funcione el sistema de transmisi\u00f3n. Al definir los descendientes del TComponent, debe anular este constructor (y marcarlo con la palabra clave anular) y realizar toda su inicializaci\u00f3n dentro de \u00e9l. Todav\u00eda est\u00e1 bien definir constructores adicionales, pero solo deben actuar como \u00abayudantes\u00bb. La instancia siempre deber\u00eda funcionar cuando se crea con el constructor Create(AOwner: TComponent); de lo contrario, no se construir\u00e1 correctamente durante la transmisi\u00f3n. La transmisi\u00f3n se utiliza, p. al guardar y cargar este componente en un formulario de Lazarus.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Notificaci\u00f3n de liberaci\u00f3n<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Si copia una referencia a la instancia, de modo que tiene dos referencias a la misma memoria, y luego una de ellas se libera, la otra se convierte en un \u00abpuntero colgante\u00bb. No se debe acceder, ya que apunta a una memoria que ya no est\u00e1 asignada. Acceder a \u00e9l puede resultar en un error de tiempo de ejecuci\u00f3n, o que se devuelva basura (ya que la memoria puede reutilizarse para otras cosas en su programa).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Usar FreeAndNil para liberar la instancia no ayuda aqu\u00ed. FreeAndNil establece en cero solo la referencia que obtuvo, no hay forma de que establezca todas las dem\u00e1s referencias autom\u00e1ticamente. Considere este c\u00f3digo:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">var\n  Obj1, Obj2: TObject;\nbegin\n  Obj1 := TObject.Create;\n  Obj2 := Obj1;\n  FreeAndNil(Obj1);\n\n  \/\/ what happens if we access Obj1 or Obj2 here?\nend;<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Al final de este bloque, el Obj1 es nulo. Si alg\u00fan c\u00f3digo tiene que acceder a \u00e9l, puede usar de manera confiable si Obj1 &lt;&gt; nil entonces&#8230; para evitar llamar a m\u00e9todos en una instancia liberada, como<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">if Obj1 &lt;&gt; nil then\n  WriteLn(Obj1.ClassName);<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Intentar acceder a un campo de una instancia nula da como resultado una excepci\u00f3n predecible en tiempo de ejecuci\u00f3n.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Entonces, incluso si alg\u00fan c\u00f3digo no verificar\u00e1 Obj1 &lt;&gt; nil, y acceder\u00e1 ciegamente al campo Obj1, obtendr\u00e1 una clara excepci\u00f3n en tiempo de ejecuci\u00f3n. Lo mismo ocurre con llamar a un m\u00e9todo virtual o llamar a un m\u00e9todo no virtual que accedi\u00f3 a un campo de una instancia nula. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Con Obj2, las cosas son menos predecibles. No es nulo, pero no es v\u00e1lido. Intentar acceder a un campo de una instancia no v\u00e1lida no nula da como resultado un comportamiento impredecible\u2009\u2014\u2009tal vez una excepci\u00f3n de violaci\u00f3n de acceso, tal vez una devoluci\u00f3n de datos basura.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Hay varias soluciones para ello:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Una soluci\u00f3n es, bueno, tener cuidado y leer la documentaci\u00f3n. No suponga nada sobre la vida \u00fatil de la referencia, si se crea mediante otro c\u00f3digo. Si una clase TCar tiene un campo que apunta a alguna instancia de TWheel, es una convenci\u00f3n que la referencia a la rueda sea v\u00e1lida mientras exista la referencia al autom\u00f3vil, y el autom\u00f3vil liberar\u00e1 sus ruedas dentro de su destructor. Pero eso es solo una convenci\u00f3n, la documentaci\u00f3n debe mencionar si est\u00e1 sucediendo algo m\u00e1s complicado.<\/li>\n\n\n\n<li>En el ejemplo anterior, justo despu\u00e9s de liberar la instancia de Obj1, simplemente puede configurar la variable Obj2 expl\u00edcitamente en nil. Eso es trivial en este caso simple.<\/li>\n\n\n\n<li>La soluci\u00f3n m\u00e1s preparada para el futuro es utilizar el mecanismo de \u00abnotificaci\u00f3n gratuita\u00bb de la clase TComponent. Se puede notificar a un componente cuando se libera otro componente y, por lo tanto, establecer su referencia en nil.<\/li>\n\n\n\n<li>Por lo tanto, obtienes algo as\u00ed como una referencia d\u00e9bil. Puede hacer frente a varios escenarios de uso, por ejemplo, puede dejar que el c\u00f3digo externo a la clase establezca su referencia, y el c\u00f3digo externo tambi\u00e9n puede liberar la instancia en cualquier momento.<\/li>\n\n\n\n<li>Esto requiere que ambas clases desciendan de TComponent. Usarlo en general se reduce a llamar a FreeNotification , RemoveFreeNotification y anular Notificaci\u00f3n.<\/li>\n\n\n\n<li>Esto requiere que ambas clases desciendan de TComponent. Usarlo en general se reduce a llamar a FreeNotification , RemoveFreeNotification y anular Notificaci\u00f3n.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Aqu\u00ed hay un ejemplo completo que muestra c\u00f3mo usar este mecanismo, junto con el constructor\/destructor y una propiedad setter. A veces se puede hacer m\u00e1s simple, pero esta es la versi\u00f3n completa que siempre es correcta \ud83d\ude42<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">type\n  TControl = class(TComponent)\n  end;\n\n  TContainer = class(TComponent)\n  private\n    FSomeSpecialControl: TControl;\n    procedure SetSomeSpecialControl(const Value: TControl);\n  protected\n    procedure Notification(AComponent: TComponent; Operation: TOperation); override;\n  public\n    destructor Destroy; override;\n    property SomeSpecialControl: TControl\n      read FSomeSpecialControl write SetSomeSpecialControl;\n  end;\n\nimplementation\n\nprocedure TContainer.Notification(AComponent: TComponent; Operation: TOperation);\nbegin\n  inherited;\n  if (Operation = opRemove) and (AComponent = FSomeSpecialControl) then\n    { set to nil by SetSomeSpecialControl to clean nicely }\n    SomeSpecialControl := nil;\nend;\n\nprocedure TContainer.SetSomeSpecialControl(const Value: TControl);\nbegin\n  if FSomeSpecialControl &lt;&gt; Value then\n  begin\n    if FSomeSpecialControl &lt;&gt; nil then\n      FSomeSpecialControl.RemoveFreeNotification(Self);\n    FSomeSpecialControl := Value;\n    if FSomeSpecialControl &lt;&gt; nil then\n      FSomeSpecialControl.FreeNotification(Self);\n  end;\nend;\n\ndestructor TContainer.Destroy;\nbegin\n  { set to nil by SetSomeSpecialControl, to detach free notification }\n  SomeSpecialControl := nil;\n  inherited;\nend;<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Observador de notificaciones gratuito (Castle Game Engine)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">En Castle Game Engine recomendamos usar TFreeNotificationObserver de la unidad CastleClassUtils en lugar de llamar directamente a FreeNotification, RemoveFreeNotification y anular Notificaci\u00f3n.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En general, usar TFreeNotificationObserver parece un poco m\u00e1s simple que usar el mecanismo FreeNotification directamente (aunque admito que es cuesti\u00f3n de gustos). Pero, en particular, cuando se debe observar la misma instancia de clase por m\u00faltiples razones, TFreeNotificationObserver es mucho m\u00e1s f\u00e1cil de usar (el uso directo de FreeNotification en este caso puede complicarse, ya que debe estar atento para no cancelar el registro de la notificaci\u00f3n demasiado pronto).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Este es el c\u00f3digo de ejemplo que usa TFreeNotificationObserver, para lograr el mismo efecto que el ejemplo en la secci\u00f3n anterior:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">type\n  TControl = class(TComponent)\n  end;\n\n  TContainer = class(TComponent)\n  private\n    FSomeSpecialControlObserver: TFreeNotificationObserver;\n    FSomeSpecialControl: TControl;\n    procedure SetSomeSpecialControl(const Value: TControl);\n    procedure SomeSpecialControlFreeNotification(const Sender: TFreeNotificationObserver);\n  public\n    constructor Create(AOwner: TComponent); override;\n    property SomeSpecialControl: TControl\n      read FSomeSpecialControl write SetSomeSpecialControl;\n  end;\n\nimplementation\n\nuses CastleComponentSerialize;\n\nconstructor TContainer.Create(AOwner: TComponent);\nbegin\n  inherited;\n  FSomeSpecialControlObserver := TFreeNotificationObserver.Create(Self);\n  FSomeSpecialControlObserver.OnFreeNotification := {$ifdef FPC}@{$endif} SomeSpecialControlFreeNotification;\nend;\n\nprocedure TContainer.SetSomeSpecialControl(const Value: TControl);\nbegin\n  if FSomeSpecialControl &lt;&gt; Value then\n  begin\n    FSomeSpecialControl := Value;\n    FSomeSpecialControlObserver.Observed := Value;\n  end;\nend;\n\nprocedure TContainer.SomeSpecialControlFreeNotification(const Sender: TFreeNotificationObserver);\nbegin\n  \/\/ set property to nil when the referenced component is freed\n  SomeSpecialControl := nil;\nend;<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Ver <a href=\"https:\/\/castle-engine.io\/custom_components\">https:\/\/castle-engine.io\/custom_components<\/a><\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-wp-embed is-provider-trasteando-por-vicio wp-block-embed-trasteando-por-vicio\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"Ny6hpBodc6\"><a href=\"https:\/\/jorgeturiel.es\/?p=314\">Introducci\u00f3n al lenguaje Pascal moderno para programadores (Parte 5)<\/a><\/blockquote><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; clip: rect(1px, 1px, 1px, 1px);\" title=\"\u00abIntroducci\u00f3n al lenguaje Pascal moderno para programadores (Parte 5)\u00bb \u2014 Trasteando por vicio\" src=\"https:\/\/jorgeturiel.es\/?p=314&#038;embed=true#?secret=ZwHHcShvyr#?secret=Ny6hpBodc6\" data-secret=\"Ny6hpBodc6\" width=\"600\" height=\"338\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Continuamos con la introducci\u00f3n al lenguaje Pascal Moderno. Esta entrada es una traducci\u00f3n al espa\u00f1ol, del texto original escrito por Michalis Kamburelis.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27,25,26],"tags":[22,23,21,24],"class_list":["post-312","post","type-post","status-publish","format-standard","hentry","category-lazarus","category-pascal","category-programacion","tag-delphi","tag-lazarus","tag-pascal","tag-programacion"],"_links":{"self":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/312","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=312"}],"version-history":[{"count":4,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/312\/revisions"}],"predecessor-version":[{"id":477,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/312\/revisions\/477"}],"wp:attachment":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=312"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=312"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=312"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}