Seguimos nuestro camino, persiguiendo la estela de cambios que nos proponía el enlace de la entrada anterior, pero sin abandonar la perspectiva que nos acompañaba en la parte I.
Hablabamos de ámbito y lo hacíamos fijandonos desde nuestro módulo de código hacia el exterior. Pero… es interesante fijar nuestra vista hacia el interior del mismo para descubrir que por fin, tras muchos años de subsistencia de un ambito de visibilidad que no nos permitía ocultar las declaraciones privadas de cada clase dentro del mismo módulo de datos, nos ha llegado un especificador de ambito que subsana el «problema»… Esto no es propio de 2007 pues ya es incorporado en las versiones anteriores pero quizás porque ambas han pasado con mas penas que gloria, es por lo que muchos puedan apercibirse de ello con los primeros pasos en el entorno de Delphi 2007. Creo recordar que en terminos coloquiales se hablaba de clases «amigas». Ahora amistad es una cosa y confianza otra… 🙂 ¡Gracias a Dios!
El especificador de ambito restrictivo (strict) modifica tanto a private como a protected para que realmente la declaraciones hechas en los respectivos ambitos se oculten. En el caso de strict protected, se entiende perfectamente que solo va a poder ser visible las declaraciones de ese ámbito en una clase descendiente. Sin embargo, parece acertado que se haya mantenido la compatibilidad hacia atras permitiendo que private y protected sigan manteniendo el mismo comportamiento, lo cual hasta cierto punto es bastante razonable… ¡lo contrario hubiera sido un disparate! 🙂
Pero lo mejor es poder verlo con un par de lineas de codigo que no van a compilar, precisamente porque vamos a violar expresamente un campo calificado como strict private desde el formulario.
unit uMain; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type THolaMundo1 = class private fSaludo: String; public procedure Saludar; end; THolaMundo2 = class strict private fSaludo: String; public procedure Saludar; end; TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var f: THolaMundo1; begin f:= THolaMundo1.Create; try f.fSaludo:= 'Hola Mundo'; //[private] podemos acceder f.Saludar; finally f.Free; end; end; procedure TForm1.Button2Click(Sender: TObject); var f: THolaMundo2; begin f:= THolaMundo2.Create; try f.fSaludo:= 'Hola Mundo'; //[strict private] no podemos acceder a fSaludo f.Saludar; finally f.Free; end; end; { THolaMundo2 } procedure THolaMundo2.Saludar; begin ShowMessage(fSaludo); end; { THolaMundo1 } procedure THolaMundo1.Saludar; begin ShowMessage(fSaludo); end; end.
El error que nos genera es: «Cannot access private symbol «THolaMundo2.Saludo».
De todas formas, cualquier programador, con independencia de haber aplicado la restricción de ambito, hubiera seguido las directrices de ocultación que nos marca la lógica de la programacion orientada a objetos y no violaría el acceso a los campos desde métodos o asignaciones directas que no fueran establecidas desde la parte publicada de la clase, que es para nosotros un contrato a cumplir. Eso nos dice la lógica…Luego cada uno, haga de su capa un sayo…
🙂
Ahora que veo esto, me he acordado de que Ian hace tiempo notó una cosa interesante: la parte publicada (published) no se rige por la lógica de ocultación, sino por la de almacenamiento. No es sólo una curiosidad. Incita a acceder a campos publicados, que no están ahí para eso.
Me gustaMe gusta
Creo que entiendo lo que quieres decir.
Veamos a ver si yo lo explico. Cuando tu inicializas valores de algunas propiedades de los objetos (componentes) en tiempo de diseño (propiedades publicadas), estas sustituyendo la inicialización de dichos campos que debería en «teoria» ocuparse los constructores del mismo en las etapas adecuadas. Todo este codigo se hace invisible a nuestros ojos y pasa desapercibido pero existe.
Es como un rio que a una altura determinada del cauce desaparece bajo tierra y aunque no lo vemos sigue presente.
Supongo que mas o menos quieres decir esto.
Salvador
Me gustaMe gusta
Quería decir que para que los valores diseñados puedan cargarse desde el DFM tienen que estar en la sección published que, lo mismo que la public, es visible desde el exterior. Esto no es bueno, porque rompe el encapsulamiento de forma atroz.
Un ejemplo: un módulo de datos que contiene objetos TQuery y similares está obligado a tener estos objetos visibles y por tanto permite modificarlos directamente desde el exterior, en vez de obligarte a crear métodos de acceso con una interfaz limitada.
No es un detalle purista. Hay muchos programas absolutamente desastrosos por la maraña que se crea cuando la gente programa de esta manera.
Me gustaMe gusta
¡Hola Salvador!
Felicidades por el blog. Me parecen interesantes tus temas.
Nico: Conozco la reflexión que hizo Ian Marteens hace tiempo sobre esa peculiaridad de la sección Published. En esencia es muy cierto: no todo lo «inspectorable» en tiempo de diseño tiene por qué ser público en tiempo de ejecución. 🙂
Pero a mí la sección que verdaderamente me causa picor es la privada. Me voy a ver muy mal diciendo esto, pero casi no utilizo la sección Private. Considero que los métodos de un objeto tienen todo el derecho de conocer (y acceder) lo que éste lleva por dentro, así sean campos y métodos heredados de clases ancestrales.
En todo caso creo que debería existir un nivel de visibilidad «seudoprivado», en la práctica con el mismo acceso que Protected, pero que el compilador reporte con algún «Hint» o «Warning» en caso de estarse accediendo desde una clase descendiente al elemento privado.
¿Qué opinan ustedes?
Un abrazo.
Al González. 🙂
Me gustaMe gusta
Muchas gracias por el comentario.
Te comento mi opinión
Yo creo que nos hemos acostumbrado mal desde los orígenes, y que ese nivel [private] que no es estrictamente privado ha permitido algunos «vicios» al programar que luego cuestan de quitar. Pasa algo parecido con lo que habitualmente llamamos clases amigas, que solo por el hecho de compartir un módulo se permiten libertades un tanto extrañas a la programación orientada a objetos.
Hay que imaginarse una clase como un contrato que hay que cumplir. No todo puede estar en la parte publica. No tiene sentido porque realmente hay métodos que solo manipula internamente ese objeto y que no tiene porque conocer ninguna instancia externa a el. Eso nos permite flexibilidad. Yo le pido a mi objeto que haga algo, pero a fin de cuentas me da igual como lo haga, lo cual refuerza la ocultación de determinados métodos.
Quizás no me he explicado bien pero el hecho de existir una parte privada y una parte protegida parece un razonamiento natural y necesario.
Un saludo,
Salvador
Me gustaMe gusta