Sign in Join
Wiki copytemporary

Understanding Interfaces/es: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Understanding Interfaces/es

OldNewLine
1+## La razón de las interfaces
2+
3+Las clases que extienden otras clases pueden llamarse sub-clases o clases derivadas. Por ejemplo, podría extenderse la clase `bicicleta` para tener una sub-clase `montañera`, y una sub-clase `paseo`. Estas clases heredan muchas de las funciones comunes de la clase `bicicleta`, pero añaden opciones únicas como la baca para la de `paseo`. Puedes llamar métodos de `bicicleta`, sabiendo que se aplican generalmente a todos los tipos de bicicleta.
4+
5+Este es un uso tradicional y estándar para las clases, dado que las sub-clases son solamente variaciones sobre un tema. Pero suponiendo que hubiera una aplicación donde existieran objetos de clase bicicleta, de automóviles, de lavacoches y otros, y en dicha aplicación se quisiera que cada clase tuviera el siguiente método:
6+
7+``` pascal
8+function EsReciclable : Boolean;
9+```
10+
11+Esto permitiría saber si el objeto contiene materiales reciclables. Se podría definir una clase de alto nivel que contuviera este método, y definir todas las clases derivadas de ella. O simplemente podrías agregar el método a cada sub-clase. O podrían usarse *interfaces*. Las interfaces simplemente pondrían orden en esta situación. Definiendo una interfaz que agrupe estos métodos juntos, establece una norma para todas las clases que implementen la interfaz. Hacen más fácil que el programador se discipline en desarrollar la aplicación; todas las clases tienen un conjunto de métodos que son idénticos y el compilador insiste que todos los métodos en una interfaz se implementen.
12+
13+Regresando al escenario del objeto reciclable, cada sub-clase hereda funciones comunes de su clase padre en particular. Esto describe la estructura básica de la sub-clase. También hereda (por implementación) las funciones comunes que se extienden por todas las clases.
14+
15+## Ejemplo de interfaz
16+
17+Como muchas ideas, un ejemplo es la mejor forma de ilustrar los conceptos. Lo haremos por etapas para que las cosas sean tan simples como sea posible. Primero, definamos una clase automóvil:
18+
19+``` pascal
20+type
21+(* Definimos nuestra clase Automóvil. *)
22+ TAutomovil = class
23+ private
24+ fMarca: String;
25+ fEdad: Byte;
26+ public
27+ (* Constructor del Automóvil. *)
28+ constructor Create (aMarca: String);
29+ published
30+ (* Propiedades del Automóvil. *)
31+ property Marca: String read fMarca;
32+ property Edad: Byte read fEdad write fEdad;
33+ end;
34+```
35+
36+Esta clase se define por defecto basado en [[TObject]] dado que no especificamos el tipo de clase base. Esta clase tiene dos propiedades, y un constructor, que se muestran aquí:
37+
38+``` pascal
39+(* Constructor de la implementación para la clase Automóvil. *)
40+ constructor TAutomovil.Create (aMarca : String);
41+ begin
42+ (* Guarda el marca del automóvil y pone la edad por defecto. *)
43+ fMarca := aMarca;
44+ fEdad := 0
45+ end;
46+```
47+
48+Aquí asignamos las dos propiedades del automóvil: su marca y edad. La marca se pasa como parámetro y asignamos una edad por defecto de 0. Ahora definiremos otra clase – una clase bicicleta:
49+
50+``` pascal
51+type
52+(* Definimos nuestra clase Bicicleta. *)
53+ TBicicleta = class
54+ private
55+ fFemenina: Boolean;
56+ fEdad: Byte;
57+ public
58+ (* Constructor de la Bicicleta. *)
59+ constructor Create (aFemenina: Boolean; aEdad: Byte);
60+ published
61+ (* Propiedades de la Bicicleta. *)
62+ property esFemenina: Boolean read fFemenina;
63+ property Edad: Byte read fEdad write fEdad;
64+ end;
65+```
66+
67+Esta clase tiene dos propiedades y un constructor como aquí se muestra:
68+
69+``` pascal
70+(* Constructor de la implementación para la clase bicicleta. *)
71+ constructor TBicicleta.Create (aFemenina: Boolean; aEdad: Byte);
72+ begin
73+ (* Save the passed parameters. *)
74+ fFemenina := aFemenina;
75+ fEdad := aEdad
76+ end;
77+```
78+
79+Esta clase es un poco distinta de la clase automóvil, lo suficiente para ver que podríamos no haber basado el automóvil en la bicicleta o la bicicleta en el automóvil. Ahora definiremos una interfaz que diga si un clase de objeto es reciclable:
80+
81+``` pascal
82+ type
83+ (* Una definición de interfaz. *)
84+ IReciclable = Interface (IInterface)
85+ (* Una sola función que da soporte a la propiedad. *)
86+ function MaterialEsReciclable: Boolean;
87+ (* Una sola propiedad. *)
88+ property esReciclable: Boolean read MaterialEsReciclable;
89+ end;
90+```
91+
92+Nuestra interfaz usa la definición estándar IInterface como base. Las definiciones de interfaces son como definiciones de clase con todos los elementos abstractos, así que no tenemos que declararlos como abstractos – lo son por defecto.
93+
94+Esta interfaz añade una propiedad esReciclable a cada clase que la implemente. Para cada clase que la implemente se garantizará que tendrá exactamente la misma forma de preguntar si es reciclable. Este es el poder y el beneficio de las interfaces – uniformidad a través de clases potencialmente muy distintas.
95+
96+Cualquier clase puede implementar tantas interfaces como se quiera – puede conformar cualquier estándar global en efecto. Nótese que debemos definir la propiedad usando una función – no podemos declarar un campo de datos `Boolean` en la interrfaz dado que las interfaces no contienen datos.
97+
98+Ahora cambiemos nuestras clases para que den soporte a esta definición de interfaz:
99+
100+``` pascal
101+ type
102+ (* Definimos nuestra clase Automóvil. *)
103+ TAutomovil = class (TInterfacedObject, IReciclable)
104+ private
105+ fMarca: String;
106+ fEdad: Byte;
107+ fEsReciclable: Boolean; { Añadido para dar soporte a IReciclable. }
108+ function MaterialEsReciclable: Boolean; { Añadido para IReciclable. }
109+ public
110+ (* Constructor del Automóvil. *)
111+ constructor Create (aMarca: String);
112+ published
113+ (* Propiedades del Automóvil. *)
114+ property Marca: String read fMarca;
115+ property Edad: Byte read fEdad write fEdad;
116+ (* Añadido para IReciclable. *)
117+ property esReciclable: Boolean read MaterialEsReciclable;
118+ end;
119+```
120+
121+Nótese que pusimos la función usada por la propiedad de interfaz `esReciclable` en la sección privada (`private`) – queremos que la propiedad la use sólo quien la llame.
122+
123+\[Nota del autor: cuando se compila, el compilador insiste en la presencia de la función `MaterialEsReciclable`, pero no en la parte más importante – la propiedad. Así como lo puede ver el autor, esto no obliga la opción predominante de la interfaz – ¡la propiedad!\]
124+
125+Ahora hemos basado nuestra clase en la clase [[TInterfaceObject]], la cual provee de algo de soporte estándar para las clases que implementan interfaces. Y hemos también basado nuestra clase en `IReciclable`, nuestra nueva interfaz.
126+
127+Pero también debemos declarar la nueva función `MaterialEsReciclable`:
128+
129+``` pascal
130+(* Función del automóvil requerida por el atributo EsReciclable. *)
131+ function TAutomovil.MaterialEsReciclable: Boolean;
132+ begin
133+ Result := fEsReciclable
134+ end;
135+```
136+
137+Y no debemos olvidar asignar este valor reciclable. Lo haremos diréctamente aquí en el constructor:
138+
139+``` pascal
140+(* Constructor para la clase automóvil. *)
141+ constructor TAutomovil.Create (aMarca: String);
142+ begin
143+ (* Guarda la marca del automóvil y asigna una edad por defecto. *)
144+ fMarca := aMarca;
145+ fEdad := 0;
146+ fEsReciclable := true { Asigna que es reciclable. }
147+ end;
148+```
149+
150+¡Vaya! Pero debemos hacer lo mismo para la clase `Bicicleta` para mostrar el auténtico efecto. Veremos el código completo para definir y usar estas clases, las cuales puedes copiar y pegar en el *Editor de Código*:
151+
152+``` pascal
153+unit Unit1;
154+
155+{$mode objfpc}{$H+}
156+
157+interface
158+
159+ uses
160+ Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs;
161+
162+ type
163+ (* Una definición de interfaz. *)
164+ IReciclable = Interface (IInterface)
165+ (* Una sola función que da soporte a la propiedad. *)
166+ function MaterialEsReciclable: Boolean;
167+ (* Una sola propiedad. *)
168+ property esReciclable: Boolean read MaterialEsReciclable;
169+ end;
170+
171+ (* Definimos nuestra clase Automóvil. *)
172+ TAutomovil = class (TInterfacedObject, IReciclable)
173+ private
174+ fMarca: String;
175+ fEdad: Byte;
176+ fEsReciclable: Boolean; { Añadido para dar soporte a IReciclable. }
177+ function MaterialEsReciclable: Boolean; { Añadido para IReciclable. }
178+ public
179+ (* Constructor del Automóvil. *)
180+ constructor Create (aMarca: String);
181+ published
182+ (* Propiedades del Automóvil. *)
183+ property Marca: String read fMarca;
184+ property Edad: Byte read fEdad write fEdad;
185+ (* Añadido para IReciclable. *)
186+ property esReciclable: Boolean read MaterialEsReciclable;
187+ end;
188+
189+ (* Definimos nuestra clase Bicicleta. *)
190+ TBicicleta = class (TInterfacedObject, IReciclable)
191+ private
192+ fFemenina: Boolean;
193+ fEdad: Byte;
194+ function MaterialEsReciclable: Boolean; { Añadido para IReciclable. }
195+ public
196+ (* Constructor de la Bicicleta. *)
197+ constructor Create (aFemenina: Boolean; aEdad: Byte);
198+ published
199+ (* Propiedades de la Bicicleta. *)
200+ property esFemenina: Boolean read fFemenina;
201+ property Edad: Byte read fEdad write fEdad;
202+ (* Añadido para IReciclable. *)
203+ property esReciclable: Boolean read MaterialEsReciclable;
204+ end;
205+
206+{ TForm1 }
207+ TForm1 = class (TForm)
208+ procedure FormCreate (Sender: TObject);
209+ private
210+ { private declarations }
211+ public
212+ { public declarations }
213+ end;
214+
215+ var
216+ Form1: TForm1;
217+
218+implementation
219+
220+{$R *.frm}
221+
222+{ TForm1 }
223+
224+ procedure TForm1.FormCreate (Sender: TObject);
225+ var
226+ biciMama: TBicicleta;
227+ cochePapa: TAutomovil;
228+ begin
229+ { Instancia los objetos bicicleta y automóvil. }
230+ biciMama := TBicicleta.Create (true, 36);
231+ cochePapa := TAutomovil.Create ('Toyota Hilux');
232+ { Pregunta a cada si cada uno si es reciclable. }
233+ if cochePapa.esReciclable then
234+ ShowMessage ('El coche de papá es reciclable.')
235+ else
236+ ShowMessage ('El coche de papá no es reciclable.');
237+ if biciMama.esReciclable then
238+ ShowMessage ('La bici de mamá es reciclable.')
239+ else
240+ ShowMessage ('La bici de mamá no es reciclable.')
241+ end;
242+
243+(* Constructor para la clase automóvil. *)
244+ constructor TAutomovil.Create (aMarca: String);
245+ begin
246+ (* Guarda la marca del automóvil y asigna una edad por defecto. *)
247+ fMarca := aMarca;
248+ fEdad := 0;
249+ fEsReciclable := true { Asigna que es reciclable. }
250+ end;
251+
252+(* Función del Automóvil requerida para el atributo esReciclable. *)
253+ function TAutomovil.MaterialEsReciclable: Boolean;
254+ begin
255+ Result := fEsReciclable
256+ end;
257+
258+(* Constructor de la implementación para la clase bicicleta. *)
259+ constructor TBicicleta.Create (aFemenina: Boolean; aEdad: Byte);
260+ begin
261+ (* Save the passed parameters. *)
262+ fFemenina := aFemenina;
263+ fEdad := aEdad
264+ end;
265+
266+(* Función de la Bicicleta requerida para el atributo esReciclable. *)
267+ function TBicicleta.MaterialEsReciclable: Boolean;
268+ begin
269+ { Vamos a presuponer que sólo las bicibletas para hombre son reciclables. }
270+ Result := not self.esFemenina
271+ end;
272+
273+end.
274+```
275+
276+Al ejecutar... [[ShowMessage]] muestra lo siguiente:
277+
278+`El coche de papá es reciclable.`\
279+`La bici de mamá no es reciclable.`
280+
281+Este post fue tomado de un artículo de internet que me pareció bien interesante para modificar y entender las interfaces. Siempre ha sido un tema tabú(?) preguntar y cuando se usan, puede darle más claridad a tu código.
282+
283+## Ver también
284+
285+- [[Accessing the Interfaces directly]]
286+- [[How To Use Interfaces]]
287+- [[Interfaces]]
288+
289+---
290+*From the Free Pascal wiki, page "Understanding Interfaces/es", as it stood on 2020-03-15 after a change by Ñuño Martínez, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history