{"id":296,"date":"2023-04-03T08:46:00","date_gmt":"2023-04-03T08:46:00","guid":{"rendered":"https:\/\/jorgeturiel.es\/?p=296"},"modified":"2023-08-11T08:51:59","modified_gmt":"2023-08-11T07:51:59","slug":"introduccion-al-lenguaje-pascal-moderno-para-programadores-parte-2","status":"publish","type":"post","link":"https:\/\/jorgeturiel.es\/?p=296","title":{"rendered":"Introducci\u00f3n al lenguaje Pascal moderno para programadores (Parte 2)"},"content":{"rendered":"\n<p>Continuamos con la introducci\u00f3n al lenguaje Pascal Moderno. <\/p>\n\n\n\n<p>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\">Units<\/h2>\n\n\n\n<p id=\"tw-target-text\">Las unidades le permiten agrupar cosas comunes (cualquier cosa que se pueda declarar), para que las usen otras unidades y programas. Son equivalentes a m\u00f3dulos y paquetes en otros idiomas. Tienen una secci\u00f3n de interfaz, donde declara lo que est\u00e1 disponible para otras unidades y programas, y luego la implementaci\u00f3n. Guarde la unidad MyUnit como myunit.pas (en min\u00fasculas con la extensi\u00f3n .pas).<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">$mode objfpc}{$H+}{$J-}\nunit MyUnit;\ninterface\n\nprocedure MyProcedure(const A: Integer);\nfunction MyFunction(const S: string): string;\n\nimplementation\n\nprocedure MyProcedure(const A: Integer);\nbegin\n  WriteLn('A + 10 is: ', A + 10);\nend;\n\nfunction MyFunction(const S: string): string;\nbegin\n  Result := S + 'strings are automatically managed';\nend;\n\nend.<\/pre><\/div>\n\n\n\n<p id=\"tw-target-text\">Los programas finales se guardan como archivos myprogram.lpr (lpr = archivo de programa Lazarus; en Delphi usar\u00eda .dpr). Tenga en cuenta que aqu\u00ed son posibles otras convenciones, p. algunos proyectos solo usan .pas para el archivo de programa principal, algunos usan .pp para unidades o programas. Aconsejo usar .pas para unidades y .lpr para programas FPC\/Lazarus. <\/p>\n\n\n\n<p>Un programa puede utilizar una unidad mediante una palabra clave uses:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">{$mode objfpc}{$H+}{$J-}\n\nprogram MyProgram;\n\nuses\n  MyUnit;\n\nbegin\n  WriteLn(MyFunction('Note: '));\n  MyProcedure(5);\nend.\n<\/pre><\/div>\n\n\n\n<p id=\"tw-target-text\">Una unidad tambi\u00e9n puede contener secciones de inicializaci\u00f3n y finalizaci\u00f3n. Este es el c\u00f3digo que se ejecuta cuando el programa comienza y finaliza.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">{$mode objfpc}{$H+}{$J-}\nunit initialization_finalization;\ninterface\n\nimplementation\n\ninitialization\n  WriteLn('Hello world!');\nfinalization\n  WriteLn('Goodbye world!');\nend.<\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Unidades que se llaman unas a otras<\/h3>\n\n\n\n<p>Una unidad tambi\u00e9n puede usar otra unidad. Se puede usar otra unidad en la secci\u00f3n de interfaz, o solo en la secci\u00f3n de implementaci\u00f3n. El primero permite definir cosas p\u00fablicas nuevas (procedimientos, tipos\u2026) adem\u00e1s de las cosas de otra unidad. Este \u00faltimo es m\u00e1s limitado (si usa una unidad solo en la secci\u00f3n de implementaci\u00f3n, puede usar sus identificadores solo en su implementaci\u00f3n).<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">{$mode objfpc}{$H+}{$J-}\nunit AnotherUnit;\ninterface\n\nuses\n  Classes;\n\n{ The \"TComponent\" type (class) is defined in the Classes unit.\n  That's why we had to use the Classes unit above. }\nprocedure DoSomethingWithComponent(var C: TComponent);\n\nimplementation\n\nuses SysUtils;\n\nprocedure DoSomethingWithComponent(var C: TComponent);\nbegin\n  { The FreeAndNil procedure is defined in the SysUtils unit.\n    Since we only refer to its name in the implementation,\n    it was OK to use the SysUtils unit in the \"implementation\" section. }\n  FreeAndNil(C);\nend;\n\nend.<\/pre><\/div>\n\n\n\n<p>No est\u00e1 permitido tener dependencias de unidades circulares en la interfaz. Es decir, dos unidades no pueden usarse entre s\u00ed en la secci\u00f3n de interfaz. La raz\u00f3n es que para \u00abcomprender\u00bb la secci\u00f3n de interfaz de una unidad, el compilador primero debe \u00abcomprender\u00bb todas las unidades que utiliza en la secci\u00f3n de interfaz. El lenguaje Pascal sigue estrictamente esta regla y permite una compilaci\u00f3n r\u00e1pida y una detecci\u00f3n completamente autom\u00e1tica en el lado del compilador de las unidades que se deben volver a compilar. No hay necesidad de usar complicados archivos Makefile para una tarea simple de compilaci\u00f3n en Pascal, y no hay necesidad de volver a compilar todo solo para asegurarse de que todas las dependencias se actualicen correctamente.<\/p>\n\n\n\n<p>Est\u00e1 bien hacer una dependencia circular entre unidades cuando al menos un \u00abuso\u00bb est\u00e1 solo en la implementaci\u00f3n. Por lo tanto, est\u00e1 bien que la unidad A use la unidad B en la interfaz y luego la unidad B use la unidad A en la implementaci\u00f3n.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Calificando identificadores con nombre de unidad<\/h3>\n\n\n\n<p>Diferentes unidades pueden definir el mismo identificador. Para mantener el c\u00f3digo f\u00e1cil de leer y buscar, por lo general debe evitarlo, pero no siempre es posible. En tales casos, la \u00faltima unidad en la cl\u00e1usula de usos \u00abgana\u00bb, lo que significa que los identificadores que introduce ocultan los mismos identificadores introducidos por unidades anteriores.<\/p>\n\n\n\n<p>Siempre puede definir expl\u00edcitamente una unidad de un identificador dado, us\u00e1ndolo como MyUnit.MyIdentifier. Esta es la soluci\u00f3n habitual cuando el identificador que desea utilizar desde MyUnit est\u00e1 oculto por otra unidad. Por supuesto, tambi\u00e9n puede reorganizar el orden de las unidades en su cl\u00e1usula de usos, aunque esto puede afectar otras declaraciones adem\u00e1s de la que est\u00e1 tratando de arreglar.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">{$mode objfpc}{$H+}{$J-}\nprogram showcolor;\n\n\/\/ Both Graphics and GoogleMapsEngine units define TColor type.\nuses Graphics, GoogleMapsEngine;\n\nvar\n  { This doesn't work like we want, as TColor ends up\n    being defined by GoogleMapsEngine. }\n  \/\/ Color: TColor;\n  { This works Ok. }\n  Color: Graphics.TColor;\nbegin\n  Color := clYellow;\n  WriteLn(Red(Color), ' ', Green(Color), ' ', Blue(Color));\nend.<\/pre><\/div>\n\n\n\n<p id=\"tw-target-text\">En el caso de las unidades, recuerda que tienen dos cl\u00e1usulas de uso: una en la interfaz y otra en la implementaci\u00f3n. La regla de que las unidades posteriores ocultan las cosas de las unidades anteriores se aplica aqu\u00ed de forma coherente, lo que significa que las unidades utilizadas en la secci\u00f3n de implementaci\u00f3n pueden ocultar los identificadores de las unidades utilizadas en la secci\u00f3n de interfaz. Sin embargo, recuerde que al leer la secci\u00f3n de la interfaz, solo importan las unidades utilizadas en la interfaz. Esto puede crear una situaci\u00f3n confusa, donde el compilador considera diferentes dos declaraciones aparentemente iguales:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">{$mode objfpc}{$H+}{$J-}\nunit UnitUsingColors;\n\n\/\/ INCORRECT example\n\ninterface\n\nuses Graphics;\n\nprocedure ShowColor(const Color: TColor);\n\nimplementation\n\nuses GoogleMapsEngine;\n\nprocedure ShowColor(const Color: TColor);\nbegin\n  \/\/ WriteLn(ColorToString(Color));\nend;\n\nend.<\/pre><\/div>\n\n\n\n<p>La unidad Graphics (de Lazarus LCL) define el tipo de TColor. Pero el compilador no podr\u00e1 compilar la unidad anterior, alegando que no implement\u00f3 un procedimiento ShowColor que coincida con la declaraci\u00f3n de la interfaz. El problema es que la unidad GoogleMapsEngine tambi\u00e9n define un tipo TColor. Y se usa solo en la secci\u00f3n de implementaci\u00f3n, por lo tanto, sombrea la definici\u00f3n de TColor solo en la implementaci\u00f3n. La versi\u00f3n equivalente de la unidad anterior, donde el error es obvio, se ve as\u00ed:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">{$mode objfpc}{$H+}{$J-}\nunit UnitUsingColors;\n\n\/\/ INCORRECT example.\n\/\/ This is what the compiler \"sees\" when trying to compile previous example\n\ninterface\n\nuses Graphics;\n\nprocedure ShowColor(const Color: Graphics.TColor);\n\nimplementation\n\nuses GoogleMapsEngine;\n\nprocedure ShowColor(const Color: GoogleMapsEngine.TColor);\nbegin\n  \/\/ WriteLn(ColorToString(Color));\nend;\n\nend.<\/pre><\/div>\n\n\n\n<p>La soluci\u00f3n es trivial en este caso, simplemente cambie la implementaci\u00f3n para usar expl\u00edcitamente TColor desde la unidad de gr\u00e1ficos. Tambi\u00e9n podr\u00eda solucionarlo moviendo el uso de GoogleMapsEngine, a la secci\u00f3n de interfaz y antes que Gr\u00e1ficos, aunque esto podr\u00eda tener otras consecuencias en casos reales, cuando UnitUsingColors definir\u00eda m\u00e1s cosas.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">{$mode objfpc}{$H+}{$J-}\nunit UnitUsingColors;\n\ninterface\n\nuses Graphics;\n\nprocedure ShowColor(const Color: TColor);\n\nimplementation\n\nuses GoogleMapsEngine;\n\nprocedure ShowColor(const Color: Graphics.TColor);\nbegin\n  \/\/ WriteLn(ColorToString(Color));\nend;\n\nend.<\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Exponer los identificadores de una unidad de otra<\/h3>\n\n\n\n<p>A veces desea tomar un identificador de una unidad y exponerlo en una nueva unidad. El resultado final deber\u00eda ser que el uso de la nueva unidad har\u00e1 que el identificador est\u00e9 disponible en el espacio de nombres.<\/p>\n\n\n\n<p>A veces, esto es necesario para preservar la compatibilidad con versiones anteriores de la unidad. A veces es bueno \u00abocultar\u00bb una unidad interna de esta manera.<\/p>\n\n\n\n<p>Esto se puede hacer redefiniendo el identificador en su nueva unidad.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">{$mode objfpc}{$H+}{$J-}\nunit MyUnit;\n\ninterface\n\nuses Graphics;\n\ntype\n  { Expose TColor from Graphics unit as TMyColor. }\n  TMyColor = TColor;\n\n  { Alternatively, expose it under the same name.\n    Qualify with unit name in this case, otherwise\n    we would refer to ourselves with \"TColor = TColor\" definition. }\n  TColor = Graphics.TColor;\n\nconst\n  { This works with constants too. }\n  clYellow = Graphics.clYellow;\n  clBlue = Graphics.clBlue;\n\nimplementation\n\nend.<\/pre><\/div>\n\n\n\n<p>Tenga en cuenta que este truco no se puede hacer tan f\u00e1cilmente con procedimientos, funciones y variables globales. Con procedimientos y funciones, podr\u00eda exponer un puntero constante a un procedimiento en otra unidad (consulte Devoluciones de llamada (tambi\u00e9n conocidas como eventos, tambi\u00e9n conocidas como punteros a funciones, tambi\u00e9n conocidas como variables de procedimiento)), pero eso parece bastante sucio.<\/p>\n\n\n\n<p>La soluci\u00f3n habitual es entonces crear funciones triviales de \u00abenvoltura\u00bb que debajo simplemente llaman a las funciones desde la unidad interna, pasando los par\u00e1metros y devolviendo valores.<\/p>\n\n\n\n<p>Para que esto funcione con variables globales, se pueden usar propiedades globales (a nivel de unidad), consulte Propiedades<\/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=\"t21UhsXvAr\"><a href=\"https:\/\/jorgeturiel.es\/?p=299\">Introducci\u00f3n al lenguaje Pascal moderno para programadores (Parte 3)<\/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 3)\u00bb \u2014 Trasteando por vicio\" src=\"https:\/\/jorgeturiel.es\/?p=299&#038;embed=true#?secret=0qEEhfCs0U#?secret=t21UhsXvAr\" data-secret=\"t21UhsXvAr\" 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],"class_list":["post-296","post","type-post","status-publish","format-standard","hentry","category-lazarus","category-pascal","category-programacion","tag-delphi","tag-lazarus","tag-pascal"],"_links":{"self":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/296","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=296"}],"version-history":[{"count":6,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/296\/revisions"}],"predecessor-version":[{"id":466,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/296\/revisions\/466"}],"wp:attachment":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=296"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=296"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=296"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}