Difference between revisions of "Object Oriented Programming with Free Pascal and Lazarus/es"

From Lazarus wiki
Jump to navigationJump to search
m (Fixed syntax highlighting)
 
(41 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{Object_Oriented_Programming_with_FreePascal_and_Lazarus}}[[Category:Castellano]][[Category:Español]]
+
{{Object Oriented Programming with Free Pascal and Lazarus}}[[Category:Castellano]][[Category:Español]]
 
=Programación Orientada a Objetos con FreePascal y Lazarus=
 
=Programación Orientada a Objetos con FreePascal y Lazarus=
 
==Introducción==
 
==Introducción==
Line 76: Line 76:
  
 
== Programando un ejemplo==
 
== Programando un ejemplo==
 
+
<div class="floatleft"> [[Image:lazarus.UnFormulario.png]]</div>
 +
<div class="floatright"> [[Image:Lazarus_Inspector_Objetos_form.png]]</div>
 
&nbsp;&nbsp;&nbsp;¡Ya está bien de ocuparse de ejemplos del mundo real! Es el momento de dedicarnos a nuestro propósito principal: programar en FreePascal.
 
&nbsp;&nbsp;&nbsp;¡Ya está bien de ocuparse de ejemplos del mundo real! Es el momento de dedicarnos a nuestro propósito principal: programar en FreePascal.
  
<div class="floatleft"> [[Image:lazarus.UnFormulario.png]] </div>&nbsp;&nbsp;&nbsp;Vamos a estudiar la creación de un sencillo formulario con un control para una aplicación en FreePascal y Lazarus.
+
&nbsp;&nbsp;&nbsp;Vamos a estudiar la creación de un sencillo formulario con un control para una aplicación en FreePascal y Lazarus.
  
<div class="floatright"> [[Image:Lazarus_Inspector_Objetos_form.png]] </div>&nbsp;&nbsp;&nbsp;Al ejecutar el IDE de Lazarus, al programador se le presenta, en diseño, un formulario en blanco, dentro del cual se pueden situar diversos controles y objetos.
+
&nbsp;&nbsp;&nbsp;Al ejecutar el IDE de Lazarus, al programador se le presenta, en diseño, un formulario en blanco, dentro del cual se pueden situar diversos controles y objetos.
  
&nbsp;&nbsp;&nbsp;Tenga en cuenta que el formulario predefinido es el mismo un objeto, con sus propias propiedades, como la posición (superior e izquierda), tamaño (altura y anchura), el color, la fuente por defecto para añadir texto, etc.
+
&nbsp;&nbsp;&nbsp;Ten en cuenta que el formulario predefinido es él mismo un objeto, con sus propias propiedades, como la posición (superior e izquierda), tamaño (altura y anchura), el color, la fuente predeterminada para añadir texto, etc.
  
 
===Usar un control===  
 
===Usar un control===  
<div class="floatright">[[Image:lazarus.InspectorTButton.png]]</div>
 
  
&nbsp;&nbsp;&nbsp;Si colocamos un botón (tipo TButton) en el formulario, este tendrá su propio conjunto de propiedades, que puede ser examinado en la ventana Inspector de Objetos. <div class="floatleft">[[Image:lazarus.UnFormularioConBoton.png]]</div>
+
&nbsp;&nbsp;&nbsp;Si colocamos un botón (tipo TButton) en el formulario, este tendrá su propio conjunto de propiedades, que puede ser examinado en la ventana '''Inspector de Objetos'''.  
  
Several of the properties have names similar to those for the Form; this is because many properties are '''Inherited''' from some common Ancestor class, which lays out how properties are to be defined and handled by the descendant classes.<div class="floatright">[[Image:Lazarus_Editor_Codigo_form.png]]</div>
+
&nbsp;&nbsp;&nbsp;Algunas de las propiedades tienen los mismos nombres que los del Formulario; esto se debe a que muchas propiedades son '''heredadas''' de algún ancestro común de ambas clases, que establece cómo son las propiedades que se definen y manejan por las clases descendientes.
 +
<div class="floatleft">[[Image:lazarus.UnFormularioConBoton.png|Un formulario con un botón]]</div><div class="floatright">[[Image:lazarus.InspectorTButton.png|Las propiedades del botón]]</div><div class="center">[[Image:Lazarus_Editor_Codigo_form.png|El código de la clase del formulario]]</div>
 +
&nbsp;&nbsp;&nbsp;Además de la pestaña ''Propiedades'', el Inspector de Objetos ofrece una pestaña llamada '''Eventos''', que da acceso a Manejadores de Eventos que son los métodos de la aplicación que se ocupan de responder, por ejemplo, a un clic de ratón (OnClick) o a algún cambio en la posición, tamaño o cualquier otra propiedad (OnChange).
  
As well as properties, the Object Inspector offers a tab called '''Events''', which gives access to Event Handlers which are methods instructing the application how to deal with things such as a mouse click on a button (OnClick) or some change in the position, size or other properties (OnChange).
+
&nbsp;&nbsp;&nbsp;La imagen física del botón en el formulario, junto con todas sus propiedades y métodos de manejo de evento, deben considerarse como una sola entidad, un '''Objeto''' en Pascal.
  
The physical image of the Button on the Form, together with all its properties and Event Handler methods, should be regarded as a single entity or '''Object''' in Pascal.
+
== Extensiones al Pascal estándar para Orientación a Objetos ==
  
== Object-Oriented Extensions to standard Pascal ==
+
&nbsp;&nbsp;&nbsp;La estructura registro de Pascal es ampliada para definir otras estructuras, cómo '''object''' (objeto) y '''class''' (clase):
  
The Pascal record structure is extended by defining an
+
=== Objeto (''object'') ===
=== Object ===
 
  
An Object is a special kind of record. The record contains all the fields that
+
&nbsp;&nbsp;&nbsp;Un objeto es un tipo especial de registro. El registro contiene todos los campos que se declaran en la definición del objeto, al igual que un registro convencional, pero ahora los procedimientos y funciones pueden ser declarados como parte del registro y se mantienen como punteros a los métodos asociados con el tipo del objeto.
are declared in the object's definition (just like a conventional record), but now procedures and functions can be declared as if they were part of the record and are held as pointers to the methods associated with the object's type.  
 
  
For example, an object could contain an array of real values, together with a Method for calculating the average.
+
&nbsp;&nbsp;&nbsp;Por ejemplo, un objeto podría contener un conjunto de valores reales, junto con un método de cálculo de la media de estos.
  
Type
+
<syntaxhighlight lang=pascal> Type
   Average = Object
+
   TMedia = Object
     NumVal: Integer;
+
     CuantosValores: Integer;
     Values: Array [1..200] of Real;
+
     Valores: Array [1..200] of Real;
     Function Mean : Real; { calculates the average value of the array }
+
     Function Media : Real; {calculo de la media de los valores de la matriz}
   End;
+
   End;</syntaxhighlight>
  
Objects can ”inherit” fields and methods from ”parent” objects. This means that these fields and methods can be used as if they were included in the objects declared as a ”child” object.
+
&nbsp;&nbsp;&nbsp;Los objetos pueden ''heredar'' los campos y los métodos del objeto ''padre''. Esto significa que estos campos y métodos pueden ser utilizados como si se incluyesen entre los objetos declarados en la definición del objeto ''hijo''.
  
Furthermore, a concept of visibility is introduced: fields, procedures and functions can be declared
+
&nbsp;&nbsp;&nbsp;Por otra parte, se introduce el concepto de visibilidad: campos, procedimientos y funciones pueden ser declaradas como públicos, protegidos o privados. De forma predeterminada, los campos y métodos son públicos y pueden ser exportados fuera de la unidad actual. Los campos y métodos protegidos sólo están disponibles para los objetos que sean descendientes del objeto en que se declaran. Los campos o métodos que se declaran privados sólo son accesibles dentro de la unidad en que son declarados: su alcance se limita a la sección ''implementation'' de la unidad.
as public, protected or private. By default, fields and methods are public, and can be exported outside the
 
current unit. Protected fields or methods are available only to objects descended from the current ancestor object. Fields or methods that are declared private are only accessible in the current unit:
 
their scope is limited to the implementation of the current unit.
 
  
=== Class ===
+
=== Clase (''class'')===
Objects are not used very often by themselves in FreePascal and Lazarus; instead, Classes are used very widely. A Class is defined in almost the same way as an Object, but is a pointer to an Object rather than the Object itself. Technically, this means that the Class is allocated on the Heap of a program, whereas the Object is allocated on the Stack.
+
&nbsp;&nbsp;&nbsp;Los objetos no son usados con frecuencia por sí mismos en FreePascal y Lazarus; en lugar de ello, se utilizan las Clases. Una clase se define casi de la misma manera que un objeto, sólo que es un puntero a un objeto en lugar del objeto en sí. Técnicamente, esto significa que la clase se asigna al [http://es.wikipedia.org/wiki/Heap montículo] de un programa, mientras que los objetos se asignan a la [http://es.wikipedia.org/wiki/Stack pila] del mismo.
  
Here is a simple example of a typical Class declaration:
+
&nbsp;&nbsp;&nbsp;Este es un ejemplo sencillo de declaración de una clase típica ([http://lazarus-ccr.sourceforge.net/docs/lcl/graphics/tpen.html clase TPen]):
 +
<syntaxhighlight lang=pascal>
 
  {-----------------------------------------}
 
  {-----------------------------------------}
  {example of Class declaration from the LCL}
+
  {ejemplo de definición de la clase TPen en la LCL}
 
  {-----------------------------------------}
 
  {-----------------------------------------}
 +
type
 
   TPen = class(TFPCustomPen)
 
   TPen = class(TFPCustomPen)
 
   private
 
   private
 +
    FHandle: HPen;
 
     FColor: TColor;
 
     FColor: TColor;
 
     FPenHandleCached: boolean;
 
     FPenHandleCached: boolean;
    FReference: TWSPenReference;
+
     procedure FreeHandle;
     procedure FreeReference;
 
    function GetHandle: HPEN;
 
    function GetReference: TWSPenReference;
 
    procedure ReferenceNeeded;
 
    procedure SetHandle(const Value: HPEN);
 
 
   protected
 
   protected
 
     procedure DoAllocateResources; override;
 
     procedure DoAllocateResources; override;
 
     procedure DoDeAllocateResources; override;
 
     procedure DoDeAllocateResources; override;
 
     procedure DoCopyProps(From: TFPCanvasHelper); override;
 
     procedure DoCopyProps(From: TFPCanvasHelper); override;
     procedure SetColor
+
     procedure SetColor(const NewColor: TColor; const NewFPColor: TFPColor); virtual;
        (const NewColor: TColor; const NewFPColor: TFPColor); virtual;
 
 
     procedure SetFPColor(const AValue: TFPColor); override;
 
     procedure SetFPColor(const AValue: TFPColor); override;
 +
    function GetHandle: HPEN;
 +
    procedure SetHandle(const Value: HPEN);
 
     procedure SetColor(Value: TColor);
 
     procedure SetColor(Value: TColor);
 
     procedure SetMode(Value: TPenMode); override;
 
     procedure SetMode(Value: TPenMode); override;
Line 152: Line 148:
 
     destructor Destroy; override;
 
     destructor Destroy; override;
 
     procedure Assign(Source: TPersistent); override;
 
     procedure Assign(Source: TPersistent); override;
     property Handle: HPEN read GetHandle write SetHandle; deprecated;
+
     property Handle: HPEN read GetHandle write SetHandle;
    property Reference: TWSPenReference read GetReference;
 
 
   published
 
   published
 
     property Color: TColor read FColor write SetColor default clBlack;
 
     property Color: TColor read FColor write SetColor default clBlack;
Line 159: Line 154:
 
     property Style default psSolid;
 
     property Style default psSolid;
 
     property Width default 1;
 
     property Width default 1;
   end;
+
   end;</syntaxhighlight>
  
 +
&nbsp;&nbsp;&nbsp;Resaltar que esta clase es definida como descendiente de otra  clase, ''TFPCustomPen'', que es el '''padre''' o '''ancestro''' de la que '''hereda''' todas sus propiedades y métodos. La clase tiene sus campos agrupados bajo las secciones
 +
*'''private''' (privado) - esto significa que los elementos definidos aquí sólo están disponibles o visibles a otras clases o procedimientos o función que se definan dentro de esta misma unidad de programa (este caso la unidad es ''Graphics'', por lo que cualquiera de las otras clases en ella definidas, tales como ''TBitMap'', ''TPicture'', etc. pueden utilizarlos). Son esencialmente variables locales (por ejemplo,''FColor'',''FPenHandleCached'') o los métodos utilizados a nivel local (''FreeHandle''), pera que puedan utilizarse o referirse desde los elementos declarados en las secciones '''protected''' o '''public'''.
 +
*'''protected''' (protegido) - los elementos aquí definidos sólo están disponibles o visibles a las clases que son descendientes de esta clase, y por tanto heredan sus propiedades y métodos
 +
*'''public''' (público) - los elementos aquí definidos están disponibles desde cualquier otra unidad de programa que incluya esta unidad en su cláusula [[Glossary/es#Uses | '''''Uses''''']]
 +
*'''published''' (publicado) - El ámbito es el mismo que en el caso de la sección '''public''', pero el compilador generará información de tipo necesaria para el almacenamiento automático de la clase. Habitualmente los elementos aquí listados son los que aparecen en el Inspector de Objetos de Lazarus; si no existe sección ''published'' todos los elementos de la sección ''public'' aparecerán en el Inspector de Objetos.
  
Note that this class is defined as an instance of another '''parent''' or '''ancestor''' class (''TFPCustomPen'') from which it '''inherits''' all its properties and methods. It has some fields of its own, grouped under
+
=== Métodos ===
*'''private''' - this means that items defined here are only available or visible to other classes or procedures/function defined within the same program unit (this example is from ''Graphics'', so any of the other classes such as ''TBitMap'', ''TPicture'' etc in the same unit can use them). They are essentially local variables (eg ''FColor'', ''FPenHandleCached'') or locally used methods (''GetHandle'', ''SetHandle'') but can be used or referred to in items declared in the '''protected''' or '''public''' sections.
+
&nbsp;&nbsp;&nbsp;Un método es exactamente los mismo que un procedimiento o una función mormales, la diferencia es que puede tener directivas adicionales.
*'''protected''' - this means that items defined here are only available or visible to classes that are descended from this '''ancestor''' class, and inherit its properties or methods
 
*'''public''' - this means that items defined here are available to any programming unit that includes the current unit in its [[Glossary#Uses | Uses]] clause
 
*'''published''' - is the same as a '''public''' section, but the compiler also generates type information that is needed for automatic streaming of these classes. Often the list of published items appear in the Object Inspector of Lazarus; if there is no '''published''' list, all the '''public''' fields usually appear in the Object Inspector.
 
  
=== Methods ===
+
&nbsp;&nbsp;&nbsp;Algunos de los métodos definidos anteriormente se etiquetan con la directiva '''virtual''', otros han sido etiquetados con la directiva '''override'''.
A method is just like a standard procedure or function, but can have some additional '''directives'''.
+
*'''virtual''' significa que el tipo real de la instancia actual de un método no se conoce en tiempo de compilación, pero se selecciona en tiempo de ejecución dependiendo de quién y cómo en realidad ejecute el método. Podría ser considerado como un [http://buscon.rae.es/draeI/SrvltGUIBusUsual?TIPO_HTML=2&TIPO_BUS=3&LEMA=comod%EDn comodín] en la definición de la clase
  
Some of the methods defined above are labelled with the directive '''virtual'''; others are labelled with the '''override''' directive.
+
*'''override''' significa que en tiempo de ejecución a nivel local, la definición dada aquí tomará el lugar de la definición heredada del ancestro de la clase, sobre todo si esta es '''virtual'''. Si desea utilizar el método definido en la clase ancestro, es necesario recurrir a él explícitamente con la cláusula '''inherited'''.
*'''virtual''' means that the type or actual instance of a method is not known at compile-time, but is selected at run-time depending on what sub-program actually calls the method. It could be considered a place-holder in the definition of the class.
 
*'''override''' means that at run-time the locally given definition can take the place of a definition inherited from an ancestor class, particularly if it was '''virtual'''. If you particularly want to use the method defined in the ancestor class, it is sometimes necessary to call it specifically with the '''inherited''' clause.
 
  
Methods with no virtual or override directive are '''static''' methods (the usual kind in Pascal). Those with a virtual or override directive are '''dynamic'''.
+
&nbsp;&nbsp;&nbsp;Los métodos sin la directiva  ''virtual'' u ''override'' son '''estáticos''' (lo habitual en Pascal). Aquellos con la directiva  ''virtual'' u ''override'' son métodos '''dinámicos'''.
  
Special instances of methods are:
+
&nbsp;&nbsp;&nbsp;Tipos especiales de métodos son:
*'''create''' - a '''constructor''' for a class, which takes care of allocating memory, collecting together all the information needed and configuring/initializing the various properties.
+
*'''Create''' - el '''constructor''' de la clase, que se encarga de la asignación de memoria, así como la recogida de toda la información necesaria y de configurar e iniciar las diversas propiedades.
*'''destroy''' - a '''destructor''' for a class, which removes all the parts of the class from the system in an orderly and logical way, and returns all its resources for the system to re-use.
 
  
=== Properties ===
+
*'''Destroy''' - el '''destructor''' de la clase, que elimina todas los elementos de la clase del sistema en forma ordenada y lógica, y devuelve todos los recursos utilizados por la misma, para que el sistema pueda reutilizarlos.
  
Properties are just like ordinary fields in a conventional Pascal record, but they can have '''read''' and/or '''write''' specifiers.
+
=== Propiedades ===
*'''read''' specifier is a field, or a function that returns a result of the correct type for the property. In the example above, the property ''Color'' has a read specifier ''FColor'', which is a local variable containing the value to be used. If a property has a '''read''' but no '''write''' specifier, it is read-only.
 
*'''write''' specifier is a field, or a procedure that will store the value of the property in a specific location. In the example above, ''Color'' has a write specifier ''SetColor'' that is a procedure (defined in the  '''protected''' section) for writing the color value to some specified location. If a property has a '''write''' but no '''read''' specifier, it is write-only.
 
*'''default''' - note that it is possible to set a '''default''' value for a property. For example, ''Color'' here is given the default value ''clBlack'', or black, at the time of creation. It could subsequently be given a different value, by a programming assignment statement, or in the Object Inspector.
 
  
 +
&nbsp;&nbsp;&nbsp;Las propiedades son semejantes a los campos de los registros convencionales de Pascal, pero pueden tener las especificaciones '''read''' y/o '''write'''
 +
*'''read''' especifica el campo o la función que devuelve el resultado del tipo correcto para la propiedad. En el ejemplo anterior, la propiedad ''Color'' tiene especificado que la variable local ''FColor'' devolverá el valor de la propiedad. Si una propiedad especifica un '''read''' pero no un '''write''', será de sólo lectura.
 +
 +
*'''write''' especifica el campo, la función o procedimiento que almacenará el valor de la propiedad en una ubicación determinada. En el ejemplo, ''Color'' tiene especificado ''SetColor'' como ''write'', por lo que será este procedimiento (definido en la sección '''protected''') el que escribirá el valor del color en la ubicación destinada para ello, ''FColor'' en este caso.  Si una propiedad especifica un '''write''' pero no un '''read''', será de sólo escritura.
 +
 +
*'''default''' - Resaltar que es posible establecer un valor '''por defecto''' para una propiedad. Por ejemplo, ''Color'' a la que aquí se da el valor por defecto ''clBlack'' (negro) en el momento de su creación. Posteriormente se puede dar un valor diferente, por una asignación en el programa, o mediante el Inspector de Objetos.
 +
 +
== Extensiones al lenguaje de Free Pascal ==
 +
 +
&nbsp;&nbsp;&nbsp;FPC incluye varias extensiones al lenguaje de la sintaxis "estándar" de Pascal para dar soporte a la programación orientada a objetos,
 +
 +
* Objetos    (chapter 5)  [[Programming Using Objects]]
 +
* Clases    (chapter 6)  [[Programming Using Classes]]
 +
* Interfaces (chapter 7)  [[Programming Using Interfaces]]
 +
* Genéricos  (chapter 8)  [[Programming Using Generics]]
 +
 +
&nbsp;&nbsp;&nbsp;Estas extensiones se describen en los capítulos indicados de la Guía Referencia del lenguaje de FPC: http://www.freepascal.org/docs.var. Enlaces a páginas de tutoría para cada concepto se incluyen arriba.
 +
 +
&nbsp;&nbsp;&nbsp;La Guía de Referencia del lenguaje incluye diagramas de sintaxis y otros detalles que no figuran en esta tutoría introductoria. 
 +
 +
&nbsp;&nbsp;&nbsp;De las cuatro características enumeradas anteriormente, '''Objetos''' y '''Clases''' forman la base de la programación orientada a objetos (POO) en FPC y Lazarus. Para los novatos en POO, la sección '''Objetos''' incluye muchos conceptos introductorios y la sección '''Clases''' elude la repetición enfatizando las similitudes y diferencias con la sintaxis de '''Objetos'''.
 +
&nbsp;&nbsp;&nbsp;En general la implementación de '''Classes''' parece ser usada más ampliamente
 +
por los desarrolladores Lazarus que Delphi. A menudo la palabra "objetos" se utiliza para referirse a lo que es en realidad una "clase" en el dialecto '''Clases''' de la POO en FPC. 
 +
 +
&nbsp;&nbsp;&nbsp;Estos documentos están redactados para minimizar cualquier confusión de terminología, pero fuera de este documento, el término "objeto" a menudo se refiere a los objetos creados a partir de una '''clase'''. De hecho, la librería de tiempo de ejecución (RTL) de FPC incluye una biblioteca con base de '''clases''' llamada ''TObject''.
 +
 +
&nbsp;&nbsp;&nbsp;Los usuarios familiarizados con la implementación POO del viejo Turbo Pascal, pueden omitir, si quieren, la sección sobre Clases ya que la implementación de objetos se basa en el dialecto de Turbo Pascal. La sección '''Clases''' resultará familiar a los usurios de Delphi ya que está basada en la sistaxis de este. Ten en cuenta que bastante de lo escrito en la  sección '''Clases''' hace refencia a conceptos de la sección '''Objetos'''. Para los desarrolladores familiarizados con diversos dialectos Object Pascal en Apple, cómo THINK y MPW,  ni los dialectos de objetos ni los de clases de FPC proporcionan una vía de migración directa. En marzo de 2009, hay discusiones en la lista de correo sobre Mac Pascal que pueden proporcionar algún apoyo al compilador (nueva sintaxis) para acceder al marco de ''Objective C/Cocoa'' de Apple. 
 +
 +
=== Conceptos Generales de Pascal Orientado a Objetos===
 +
 +
&nbsp;&nbsp;&nbsp;La POO provee formas distintas para manejar y encapsular datos y dirigir el flujo del programa en comparación con otras caracteristicas y estructuras disponibles el el lenguaje de programación.
 +
 +
&nbsp;&nbsp;&nbsp;La POO a menudo se presta al modelado de ciertas aplicaciones, tales como interfaces de usuario gráficas (GUI) y sistemas físicos de una manera que parece más natural. Sin embargo la POO no es apropiada para todas las aplicaciones. El control del programa  no es tan explícito como en la más básica construcción procedimental Pascal. Para obtener el máximo beneficio de la POO, se requiere, a menudo, la comprensión de grandes bibliotecas de clases lo que puede traducirse en una empinada curva de aprendizaje. El mantenimiento de grandes aplicaciones de código POO tiene sus ventajas e inconvenientes respecto a mantener código estrictamente procedural. Hay muchas fuentes para el aprendizaje de análisis orientado a objetos, diseño y técnicas de programación que están fuera del alcance de esta guía.
 +
 +
&nbsp;&nbsp;&nbsp;Hay numerosos lenguajes de programación que incorporan características de POO como extensiones o en la base del mismo. Por tanto, hay muchos términos diferentes para describir conceptos OO. Incluso dentro de FPC, algunos términos se solapan. En general, la POO por lo común consiste en el concepto de un objeto de programación (o unidad de información), que de forma explícita combina y encapsula un conjunto relacionado de datos y procedimientos que actúan sobre los datos. Estos datos son generalmente persistentes durante la ejecución del programa, pero con mecanismos para reducir algunos de los problemas inherentes a la declaración de variables globales. Además, los lenguajes OOP permiten a los objetos, de modo incremental, ser modificados y/o ampliados sobre la base del objeto previamente definido. Esta característica está relacionada generalmente con los términos ''herencia'' y ''polimorfismo''. Muchos lenguajes POO utilizan los términos ''método'' o ''mensaje'', refiriéndose a los procedimientos que pertenecen a un objeto. Gran parte del poder de la POO se debe al enlace dimámico en tiempo de ejecución en lugar de enlazar en la compilación. Este enlace dinámico de los métodos es similar al uso de variables de procedimiento y parámetros de procedimiento, pero con una cohesión sintáctica mayor, la encapsulación con los datos está relacionada con heredar también el comportamiento de los métodos previamente definidos. Las páginas que siguen presentan un wiki como punto de partida para descubrir más sobre el análisis, diseño y programación a la manera de la Orientación a Objetos.
  
 
== Más información ==
 
== Más información ==
Line 193: Line 219:
 
&nbsp;&nbsp;&nbsp;Este artículo sólo ha arañado la superficie del tema. Para más detalles, se recomienda encarecidamente leer los [http://lazarus-ccr.sourceforge.net/fpcdoc/ref/ref.html '''manuales de FreePascal'''] , especialmente los capítulos 4 [http://lazarus-ccr.sourceforge.net/fpcdoc/ref/refch4.html#x43-460004 '''Objetos'''] y 5 [http://lazarus-ccr.sourceforge.net/fpcdoc/ref/refch5.html#x50-560005 '''Clases'''].
 
&nbsp;&nbsp;&nbsp;Este artículo sólo ha arañado la superficie del tema. Para más detalles, se recomienda encarecidamente leer los [http://lazarus-ccr.sourceforge.net/fpcdoc/ref/ref.html '''manuales de FreePascal'''] , especialmente los capítulos 4 [http://lazarus-ccr.sourceforge.net/fpcdoc/ref/refch4.html#x43-460004 '''Objetos'''] y 5 [http://lazarus-ccr.sourceforge.net/fpcdoc/ref/refch5.html#x50-560005 '''Clases'''].
  
* [[User:Kirkpatc|Kirkpatc]] 11:04, 20 July 2008 (CEST)
+
== Ver también==
* Versión en castellano (español) [[User:Iskraelectrica | iskraelectrica (jldc)]] / julio de 2008.
+
*[[Console Mode Pascal/es|Programación con Pascal en modo consola]]
 +
 
 +
== Enlaces externos ==
 +
*[http://es.wikipedia.org/wiki/Programación_orientada_a_objetos Programación orientada a objetos]
 +
*[http://es.wikipedia.org/wiki/Análisis_y_diseño_orientado_a_objetos Análisis y diseño orientado a objetos]
 +
*[http://es.wikipedia.org/wiki/Diseño_orientado_a_objetos Diseño orientado a objetos]
 +
 
 +
* Versión en castellano (español) [[User:Iskraelectrica | iskraelectrica (jldc)]] / agosto de 2010.

Latest revision as of 12:24, 21 February 2020

English (en) español (es) français (fr) magyar (hu) italiano (it) македонски (mk) русский (ru) 中文(中国大陆)‎ (zh_CN) 中文(台灣)‎ (zh_TW)

Programación Orientada a Objetos con FreePascal y Lazarus

Introducción

   Hay muchas excelentes tutorías sobre Pascal, pero esta pretender iniciar sobre la Programación Orientada a Objetos, que es una extensión del Pascal estándar, ofrecida por Turbo-pascal, Delphi y FreePascal/Lazarus.

   Un Objeto es una extensión de la estructura registro del Pascal estándar.

   La programación estándar en modo texto de Pascal es, cómo las aplicaciones Unix tradicionales, buena para hacer cualquier tarea y que se haga muy bien. Pero esta tarea puede ser algo compleja y que ofrezca al usuario variado menú de opciones, pero sin embargo está limitado a obedecer ordenes que se escriben por el teclado y mostrar las respuestas en un terminal o impresora.

   Con el fin de proporcionar una interfaz gráfica de usuario (GUI), es habitual recurrir a algún tipo de programación orientada a objetos (a menudo haciendo uso de C, o alguna de sus variantes, o Visual Basic, o alguna de las variantes de OO de Pascal, como FreePascal con o sin Lazarus).

   En una interfaz gráfica de usuario (GUI) al usuario se le presenta una pantalla con un gran número de imágenes dispuestas en forma estructurada, que consta de un conjunto de herramientas o artefactos que están asociados con diversas acciones, tales como

  • seleccionar de un menú,
  • abrir o guardar archivos,
  • conectar a Internet,
  • realización de cálculos numéricos, etc.

   Del usuario se espera que mueva un ratón u otro tipo de puntero o herramienta de selección sobre la pantalla, para seleccionar las acciones que se realizarán en respuesta a un clic de ratón o la pulsación de una tecla.

   Si bien sistemas para realizar una compleja interfaz gráfica de usuario pueden ser escritos en Pascal estándar o cualquier otro lenguaje de programación, es mucho más fácil utilizar un sistema orientado a objeto s, en el que cada elemento gráfico en la pantalla tiene todas sus propiedades, procedimientos y funciones relacionadas con su utilización unidas juntas en una estructura común, en un objeto.

Objetos: una analogía con el mundo real

   Considera la analogía de una muestra de sangre recogida en un hospital o en la consulta del médico.

Análisis de sangre

   La muestra de sangre es ciertamente un objeto; se ha asociado a ella una gran cantidad de información, documentos y otros objetos físicos.

  • Tubo de muestra, del tipo adecuado a las pruebas que el médico quiere realizar.
  • Reglamento interno (o método, procedimiento de operación estándar) para dirigir a la enfermera o técnico en la recogida de la muestra.
    • qué tipo de tubo debe utilizar,
    • cómo debe procesar la muestra,
    • cómo almacenarla hasta que se envía al laboratorio.
  • Etiqueta en el tubo con detalles sobre
    • identificador de la muestra
    • datos del paciente, nombre, fecha de nacimiento,...
    • fecha y hora de toma de la muestra
    • pruebas solicitadas.
  • Formulario de solicitud que acompaña a la muestra al laborarorio, con datos como
    • Identificador de la muestra
    • Identificación del médico solicitante
    • que pruebas ha pedido el médico
    • información detallada sobre el paciente
    • el posible diagnóstico cuya confirmación que se busca.

   Una copia del formulario de solicitud se guarda en el historial del paciente y sirve para recordar al médico que debe tener los resultados en un tiempo adecuado.

  • En el laboratorio: Se usa una Metodología para determinar
    • la forma en que la muestra se analiza,
    • qué aparatos hay que utilizar,
    • Cómo se deben calibrar y manejar los aparatos,
    • cómo archivar los resultados, y el formato de los mismos,
    • remitir los informes al médico.

   Los resultados reales son un registro que utiliza el médico para ayudar al diagnóstico, y una copia de los mismos se archivo en el historial del paciente.

   La muestra física puede ser conservada para referencia, confirmación o nuevos ensayos, o será eliminada por algún medio adecuado; habrá un método regulado que describirá como hacer esto.

   EL médico no necesita explicar todos los detalles e instrucciones cada vez que se toma una muestra, de hecho puede tener muy poco conocimiento sobre cómo se procesa la muestra en el laboratorio. Los detalles de los diversos procesos son heredados de tomas de muestras y análisis previos. Habrá un plan genérico para toda la secuencia, y así podríamos pensar en la muestra de sangre, todos sus documentos y datos, y los métodos de proeceso subyacentes, como un objeto complejo.

   En la cabeza del médico, la muestra de sangre es identificada con los resultados, así como con las enfermeras y técnicos de laboratorio, el tubo, la etiqueta y las condiciones de almacenamiento, constituyendo todo ello una única entidad.

Otro ejemplo: automóvil

Si no le gusta la sangre, el mismo tipo de razonamiento puede aplicarse a un coche enviado a un taller para su reparación. Podría consistir en:

  • el vehículo
  • documentos en poder del propietario: registro o licencia (incluida la matrícula de un vehículo), los seguros, los recibos de compra, repuestos, reparaciones, etc.
  • la historia del consumo de combustible
  • los conductores autorizados a utilizar el vehículo, con los datos de su licencia
  • informes de otros servicios prestados por el taller
  • métodos o procedimientos que deben seguirse para el proceso de revisión y mantenimiento
  • métodos que deben seguirse para reparaciones no habituales, etc.
  • datos de facturación para el cliente

Programando un ejemplo

lazarus.UnFormulario.png
Lazarus Inspector Objetos form.png

   ¡Ya está bien de ocuparse de ejemplos del mundo real! Es el momento de dedicarnos a nuestro propósito principal: programar en FreePascal.

   Vamos a estudiar la creación de un sencillo formulario con un control para una aplicación en FreePascal y Lazarus.

   Al ejecutar el IDE de Lazarus, al programador se le presenta, en diseño, un formulario en blanco, dentro del cual se pueden situar diversos controles y objetos.

   Ten en cuenta que el formulario predefinido es él mismo un objeto, con sus propias propiedades, como la posición (superior e izquierda), tamaño (altura y anchura), el color, la fuente predeterminada para añadir texto, etc.

Usar un control

   Si colocamos un botón (tipo TButton) en el formulario, este tendrá su propio conjunto de propiedades, que puede ser examinado en la ventana Inspector de Objetos.

   Algunas de las propiedades tienen los mismos nombres que los del Formulario; esto se debe a que muchas propiedades son heredadas de algún ancestro común de ambas clases, que establece cómo son las propiedades que se definen y manejan por las clases descendientes.

Un formulario con un botón
Las propiedades del botón
El código de la clase del formulario

   Además de la pestaña Propiedades, el Inspector de Objetos ofrece una pestaña llamada Eventos, que da acceso a Manejadores de Eventos que son los métodos de la aplicación que se ocupan de responder, por ejemplo, a un clic de ratón (OnClick) o a algún cambio en la posición, tamaño o cualquier otra propiedad (OnChange).

   La imagen física del botón en el formulario, junto con todas sus propiedades y métodos de manejo de evento, deben considerarse como una sola entidad, un Objeto en Pascal.

Extensiones al Pascal estándar para Orientación a Objetos

   La estructura registro de Pascal es ampliada para definir otras estructuras, cómo object (objeto) y class (clase):

Objeto (object)

   Un objeto es un tipo especial de registro. El registro contiene todos los campos que se declaran en la definición del objeto, al igual que un registro convencional, pero ahora los procedimientos y funciones pueden ser declarados como parte del registro y se mantienen como punteros a los métodos asociados con el tipo del objeto.

   Por ejemplo, un objeto podría contener un conjunto de valores reales, junto con un método de cálculo de la media de estos.

 Type
   TMedia = Object
     CuantosValores: Integer;
     Valores: Array [1..200] of Real;
     Function Media  : Real; {calculo de la media de los valores de la matriz}
   End;

   Los objetos pueden heredar los campos y los métodos del objeto padre. Esto significa que estos campos y métodos pueden ser utilizados como si se incluyesen entre los objetos declarados en la definición del objeto hijo.

   Por otra parte, se introduce el concepto de visibilidad: campos, procedimientos y funciones pueden ser declaradas como públicos, protegidos o privados. De forma predeterminada, los campos y métodos son públicos y pueden ser exportados fuera de la unidad actual. Los campos y métodos protegidos sólo están disponibles para los objetos que sean descendientes del objeto en que se declaran. Los campos o métodos que se declaran privados sólo son accesibles dentro de la unidad en que son declarados: su alcance se limita a la sección implementation de la unidad.

Clase (class)

   Los objetos no son usados con frecuencia por sí mismos en FreePascal y Lazarus; en lugar de ello, se utilizan las Clases. Una clase se define casi de la misma manera que un objeto, sólo que es un puntero a un objeto en lugar del objeto en sí. Técnicamente, esto significa que la clase se asigna al montículo de un programa, mientras que los objetos se asignan a la pila del mismo.

   Este es un ejemplo sencillo de declaración de una clase típica (clase TPen):

 {-----------------------------------------}
 {ejemplo de definición de la clase TPen en la LCL}
 {-----------------------------------------}
type
  TPen = class(TFPCustomPen)
  private
    FHandle: HPen;
    FColor: TColor;
    FPenHandleCached: boolean;
    procedure FreeHandle;
  protected
    procedure DoAllocateResources; override;
    procedure DoDeAllocateResources; override;
    procedure DoCopyProps(From: TFPCanvasHelper); override;
    procedure SetColor(const NewColor: TColor; const NewFPColor: TFPColor); virtual;
    procedure SetFPColor(const AValue: TFPColor); override;
    function GetHandle: HPEN;
    procedure SetHandle(const Value: HPEN);
    procedure SetColor(Value: TColor);
    procedure SetMode(Value: TPenMode); override;
    procedure SetStyle(Value: TPenStyle); override;
    procedure SetWidth(value: Integer); override;
  public
    constructor Create; override;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    property Handle: HPEN read GetHandle write SetHandle;
  published
    property Color: TColor read FColor write SetColor default clBlack;
    property Mode default pmCopy;
    property Style default psSolid;
    property Width default 1;
  end;

   Resaltar que esta clase es definida como descendiente de otra clase, TFPCustomPen, que es el padre o ancestro de la que hereda todas sus propiedades y métodos. La clase tiene sus campos agrupados bajo las secciones

  • private (privado) - esto significa que los elementos definidos aquí sólo están disponibles o visibles a otras clases o procedimientos o función que se definan dentro de esta misma unidad de programa (este caso la unidad es Graphics, por lo que cualquiera de las otras clases en ella definidas, tales como TBitMap, TPicture, etc. pueden utilizarlos). Son esencialmente variables locales (por ejemplo,FColor,FPenHandleCached) o los métodos utilizados a nivel local (FreeHandle), pera que puedan utilizarse o referirse desde los elementos declarados en las secciones protected o public.
  • protected (protegido) - los elementos aquí definidos sólo están disponibles o visibles a las clases que son descendientes de esta clase, y por tanto heredan sus propiedades y métodos
  • public (público) - los elementos aquí definidos están disponibles desde cualquier otra unidad de programa que incluya esta unidad en su cláusula Uses
  • published (publicado) - El ámbito es el mismo que en el caso de la sección public, pero el compilador generará información de tipo necesaria para el almacenamiento automático de la clase. Habitualmente los elementos aquí listados son los que aparecen en el Inspector de Objetos de Lazarus; si no existe sección published todos los elementos de la sección public aparecerán en el Inspector de Objetos.

Métodos

   Un método es exactamente los mismo que un procedimiento o una función mormales, la diferencia es que puede tener directivas adicionales.

   Algunos de los métodos definidos anteriormente se etiquetan con la directiva virtual, otros han sido etiquetados con la directiva override.

  • virtual significa que el tipo real de la instancia actual de un método no se conoce en tiempo de compilación, pero se selecciona en tiempo de ejecución dependiendo de quién y cómo en realidad ejecute el método. Podría ser considerado como un comodín en la definición de la clase
  • override significa que en tiempo de ejecución a nivel local, la definición dada aquí tomará el lugar de la definición heredada del ancestro de la clase, sobre todo si esta es virtual. Si desea utilizar el método definido en la clase ancestro, es necesario recurrir a él explícitamente con la cláusula inherited.

   Los métodos sin la directiva virtual u override son estáticos (lo habitual en Pascal). Aquellos con la directiva virtual u override son métodos dinámicos.

   Tipos especiales de métodos son:

  • Create - el constructor de la clase, que se encarga de la asignación de memoria, así como la recogida de toda la información necesaria y de configurar e iniciar las diversas propiedades.
  • Destroy - el destructor de la clase, que elimina todas los elementos de la clase del sistema en forma ordenada y lógica, y devuelve todos los recursos utilizados por la misma, para que el sistema pueda reutilizarlos.

Propiedades

   Las propiedades son semejantes a los campos de los registros convencionales de Pascal, pero pueden tener las especificaciones read y/o write

  • read especifica el campo o la función que devuelve el resultado del tipo correcto para la propiedad. En el ejemplo anterior, la propiedad Color tiene especificado que la variable local FColor devolverá el valor de la propiedad. Si una propiedad especifica un read pero no un write, será de sólo lectura.
  • write especifica el campo, la función o procedimiento que almacenará el valor de la propiedad en una ubicación determinada. En el ejemplo, Color tiene especificado SetColor como write, por lo que será este procedimiento (definido en la sección protected) el que escribirá el valor del color en la ubicación destinada para ello, FColor en este caso. Si una propiedad especifica un write pero no un read, será de sólo escritura.
  • default - Resaltar que es posible establecer un valor por defecto para una propiedad. Por ejemplo, Color a la que aquí se da el valor por defecto clBlack (negro) en el momento de su creación. Posteriormente se puede dar un valor diferente, por una asignación en el programa, o mediante el Inspector de Objetos.

Extensiones al lenguaje de Free Pascal

   FPC incluye varias extensiones al lenguaje de la sintaxis "estándar" de Pascal para dar soporte a la programación orientada a objetos,

   Estas extensiones se describen en los capítulos indicados de la Guía Referencia del lenguaje de FPC: http://www.freepascal.org/docs.var. Enlaces a páginas de tutoría para cada concepto se incluyen arriba.

   La Guía de Referencia del lenguaje incluye diagramas de sintaxis y otros detalles que no figuran en esta tutoría introductoria.

   De las cuatro características enumeradas anteriormente, Objetos y Clases forman la base de la programación orientada a objetos (POO) en FPC y Lazarus. Para los novatos en POO, la sección Objetos incluye muchos conceptos introductorios y la sección Clases elude la repetición enfatizando las similitudes y diferencias con la sintaxis de Objetos.    En general la implementación de Classes parece ser usada más ampliamente por los desarrolladores Lazarus que Delphi. A menudo la palabra "objetos" se utiliza para referirse a lo que es en realidad una "clase" en el dialecto Clases de la POO en FPC.

   Estos documentos están redactados para minimizar cualquier confusión de terminología, pero fuera de este documento, el término "objeto" a menudo se refiere a los objetos creados a partir de una clase. De hecho, la librería de tiempo de ejecución (RTL) de FPC incluye una biblioteca con base de clases llamada TObject.

   Los usuarios familiarizados con la implementación POO del viejo Turbo Pascal, pueden omitir, si quieren, la sección sobre Clases ya que la implementación de objetos se basa en el dialecto de Turbo Pascal. La sección Clases resultará familiar a los usurios de Delphi ya que está basada en la sistaxis de este. Ten en cuenta que bastante de lo escrito en la sección Clases hace refencia a conceptos de la sección Objetos. Para los desarrolladores familiarizados con diversos dialectos Object Pascal en Apple, cómo THINK y MPW, ni los dialectos de objetos ni los de clases de FPC proporcionan una vía de migración directa. En marzo de 2009, hay discusiones en la lista de correo sobre Mac Pascal que pueden proporcionar algún apoyo al compilador (nueva sintaxis) para acceder al marco de Objective C/Cocoa de Apple.

Conceptos Generales de Pascal Orientado a Objetos

   La POO provee formas distintas para manejar y encapsular datos y dirigir el flujo del programa en comparación con otras caracteristicas y estructuras disponibles el el lenguaje de programación.

   La POO a menudo se presta al modelado de ciertas aplicaciones, tales como interfaces de usuario gráficas (GUI) y sistemas físicos de una manera que parece más natural. Sin embargo la POO no es apropiada para todas las aplicaciones. El control del programa no es tan explícito como en la más básica construcción procedimental Pascal. Para obtener el máximo beneficio de la POO, se requiere, a menudo, la comprensión de grandes bibliotecas de clases lo que puede traducirse en una empinada curva de aprendizaje. El mantenimiento de grandes aplicaciones de código POO tiene sus ventajas e inconvenientes respecto a mantener código estrictamente procedural. Hay muchas fuentes para el aprendizaje de análisis orientado a objetos, diseño y técnicas de programación que están fuera del alcance de esta guía.

   Hay numerosos lenguajes de programación que incorporan características de POO como extensiones o en la base del mismo. Por tanto, hay muchos términos diferentes para describir conceptos OO. Incluso dentro de FPC, algunos términos se solapan. En general, la POO por lo común consiste en el concepto de un objeto de programación (o unidad de información), que de forma explícita combina y encapsula un conjunto relacionado de datos y procedimientos que actúan sobre los datos. Estos datos son generalmente persistentes durante la ejecución del programa, pero con mecanismos para reducir algunos de los problemas inherentes a la declaración de variables globales. Además, los lenguajes OOP permiten a los objetos, de modo incremental, ser modificados y/o ampliados sobre la base del objeto previamente definido. Esta característica está relacionada generalmente con los términos herencia y polimorfismo. Muchos lenguajes POO utilizan los términos método o mensaje, refiriéndose a los procedimientos que pertenecen a un objeto. Gran parte del poder de la POO se debe al enlace dimámico en tiempo de ejecución en lugar de enlazar en la compilación. Este enlace dinámico de los métodos es similar al uso de variables de procedimiento y parámetros de procedimiento, pero con una cohesión sintáctica mayor, la encapsulación con los datos está relacionada con heredar también el comportamiento de los métodos previamente definidos. Las páginas que siguen presentan un wiki como punto de partida para descubrir más sobre el análisis, diseño y programación a la manera de la Orientación a Objetos.

Más información

   Este artículo sólo ha arañado la superficie del tema. Para más detalles, se recomienda encarecidamente leer los manuales de FreePascal , especialmente los capítulos 4 Objetos y 5 Clases.

Ver también

Enlaces externos