8 | | A los elementos de una estructura se les suele llamar campos, pero en una clase hay que distinguir los métodos de los miembros.Un método es una función de una clase con un prototipo o definición conocida y fija, es decir, que el tipo devuelto y los argumentos, incluidos sus nombres, están prefijados de antemano.Todos los demás elementos de una clase se denominarán miembros. Nótese que un elemento de tipo {{{Code}}} no es un método. |
| 10 | A los elementos de una estructura se les suele llamar campos, pero en una clase hay que distinguir los métodos de los miembros. Un método es una función de una clase con un prototipo o definición conocida y fija, es decir, que el tipo devuelto y los argumentos, incluidos sus nombres, están prefijados de antemano.Todos los demás elementos de una clase se denominarán miembros. Nótese que un elemento de tipo {{{Code}}} no es un método. |
18 | | == Clases primarias == |
| 20 | === El miembro privado reservado _this === |
| 21 | |
| 22 | Todos los NameBlock, sean o no instancia de una clase, tienen un miembro privado llamado _this al que se puede acceder desde todos sus métodos. |
| 23 | |
| 24 | {{{ |
| 25 | //Example of using implicit private member _this |
| 26 | NameBlock a = |
| 27 | [[ |
| 28 | Text _.name = "a"; |
| 29 | Text getName(Real unused) { _this::_.name } |
| 30 | ]]; |
| 31 | |
| 32 | //User cannot overwrite _this due to it's a reserved word |
| 33 | NameBlock b = |
| 34 | [[ |
| 35 | Text _.name = "b"; |
| 36 | NameBlock _this = a; |
| 37 | Text getName(Real unused) { _this::_.name } |
| 38 | ]]; |
| 39 | |
| 40 | }}} |
| 41 | |
| 42 | === Uso de miembros de tipo Code === |
| 43 | |
| 44 | En OOP no se recomienda el uso de miembros que apunten a funciones asignables como pueden ser los punteros de funciones en C++ o los objetos de tipo Code en TOL. Una función asignable pretende recoger comportamientos polimórficos impredecibles y eso en OOP se trata mediante herencia de métodos virtuales. |
| 45 | |
| 46 | TOL dará un un mensaje de aviso cuando esto ocurra, aunque se permitirá su uso por si fuera necesario en casos extremos. |
| 47 | |
| 48 | En tales casos las funciones así utilizadas no tendrán acceso al ámbito de la clase pues no se trata de verdaderos métodos. |
| 49 | |
| 50 | Aún más peligroso resulta usar estos miembros de tipo Code dentro de un !NameBlock genérico, no instancia de clase, puesto que en ellos es imposible distinguir si fue creado como método o como objeto, por lo que tendrá acceso al ámbito del !NameBlock y sólo debería ser asignado a verdaderos métodos del mismo, nunca a objetos externos. |
| 51 | |
| 52 | Especialmente dañino resultaría que una misma función externa fuera asignada a miembros de tipo Code de diferentes !NameBlock's no globales, o bien que esa función se usara además fuera de ellos, pues ello podría incluso ocasionar una caída de TOL. |
| 53 | |
| 54 | === Miembros y métodos estáticos === |
| 55 | |
| 56 | Si la declaración de un elemento de la clase va precedida por la palabra reservada '''Static''', entonces dicho elemento será compartido por tadas las intancias de dicha clase y para referirse a ellos fuera del ámbito de la misma será necesario utilizar la sintaxis {{{<nombre_de_clase>::<nombre_de_elemento>}}} |
| 57 | |
| 58 | == Instancias == |
| 59 | Una instancia de una clase es un NameBlock que cumple la API definida por dicha clase y define al menos todos los miembros sin valor por defecto. Obsérvese que el orden de declaración de los miembros es irrelevante e independiente del orden de herencia de las clases. |
| 60 | |
| 61 | {{{ |
| 62 | VectorDoc.Ser vd.ser = |
| 63 | [[ |
| 64 | Text _.name = "Viernes"; |
| 65 | Text _.description = "Es 1 los días viernes y 0 el resto"; |
| 66 | Serie _ser = CalInd(WD(5),C) |
| 67 | ]]; |
| 68 | |
| 69 | VectorDoc.Mat vd.mat = |
| 70 | [[ |
| 71 | Text _.name = "Constante"; |
| 72 | Matrix _mat = SetCol(NCopy(1,100)); |
| 73 | Text _.description = "Siempre vale 1" |
| 74 | ]]; |
| 75 | }}} |
| 76 | |
| 77 | Para ser más exacto sólo esposibe crear instancias de una clase no virtual, es decir, con todos los métodos implementados, lo cual se explicará más adelante. |
| 78 | |
| 79 | == Clases == |
| 80 | |
| 81 | === Clases primarias === |
107 | | == Instancias == |
108 | | Una instancia de una clase no virtual, es decir, con todos los métodos implementados, es un NameBlock que cumple la API definida por dicha clase y define al menos todos los miembros sin valor por defecto. Obsérvese que el orden de declaración de los miembros es irrelevante e independiente del orden de herencia de las clases. |
109 | | |
110 | | {{{ |
111 | | VectorDoc.Ser vd.ser = |
112 | | [[ |
113 | | Text _.name = "Viernes"; |
114 | | Text _.description = "Es 1 los días viernes y 0 el resto"; |
115 | | Serie _ser = CalInd(WD(5),C) |
116 | | ]]; |
117 | | |
118 | | VectorDoc.Mat vd.mat = |
119 | | [[ |
120 | | Text _.name = "Constante"; |
121 | | Matrix _mat = SetCol(NCopy(1,100)); |
122 | | Text _.description = "Siempre vale 1" |
123 | | ]]; |
124 | | }}} |
125 | | |
126 | | == Las clases vistas como tipos de usuario == |
127 | | |
128 | | Los nombres de clase funcionarán como tipos definidos por el usuario a todos los efectos, salvo alguna excepción debida a las limitaciones del parser de TOL y que quedarán debidamente documentadas. Es posible entonces declarar argumentos de función de una clase determinada lo cual admitirá cualquier NameBlock que sea instancia de esa clase o cualquier clase heredada de ella. |
129 | | |
130 | | {{{ |
131 | | Matrix sum(Vector a, Vector b) |
132 | | { |
133 | | a::get.data(0) + b::get.data(0) |
134 | | }; |
135 | | |
136 | | Matrix c = sum(vd.ser, vd.mat); |
137 | | }}} |
138 | | |
139 | | == Otros ejemplos de clases == |
| 169 | === Otros ejemplos de clases === |
172 | | == Predeclaración de clases == |
173 | | |
174 | | Es posible predeclarar una clase sin definir sus métodos ni las clases de las que hereda, para poder ser usada dentro de otra clase que a su vez la use, tal y como se ilstra en el siguiente ejemplo: |
| 203 | === Las clases vistas como tipos de usuario === |
| 204 | |
| 205 | Los nombres de clase funcionarán como tipos definidos por el usuario a todos los efectos, salvo alguna excepción debida a las limitaciones del parser de TOL y que quedarán debidamente documentadas. Es posible entonces declarar argumentos de función de una clase determinada lo cual admitirá cualquier NameBlock que sea instancia de esa clase o cualquier clase heredada de ella. |
| 206 | |
| 207 | {{{ |
| 208 | Matrix sum(Vector a, Vector b) |
| 209 | { |
| 210 | a::get.data(0) + b::get.data(0) |
| 211 | }; |
| 212 | |
| 213 | Matrix c = sum(vd.ser, vd.mat); |
| 214 | }}} |
| 215 | |
| 216 | === Predeclaración de clases === |
| 217 | |
| 218 | Es posible predeclarar una clase sin definir sus métodos ni las clases de las que hereda, para poder ser usada dentro de otra clase que a su vez la precise, tal y como se ilstra en el siguiente ejemplo: |
204 | | |
205 | | == El miembro privado reservado _this == |
206 | | |
207 | | Todos los NameBlock, sean o no instancia de una clase, tienen un miembro privado llamado _this al que se puede acceder desde todos sus métodos. |
208 | | |
209 | | {{{ |
210 | | //Example of using implicit private member _this |
211 | | NameBlock a = |
212 | | [[ |
213 | | Text _.name = "a"; |
214 | | Text getName(Real unused) { _this::_.name } |
215 | | ]]; |
216 | | |
217 | | //User cannot overwrite _this due to it's a reserved word |
218 | | NameBlock b = |
219 | | [[ |
220 | | Text _.name = "b"; |
221 | | NameBlock _this = a; |
222 | | Text getName(Real unused) { _this::_.name } |
223 | | ]]; |
224 | | |
225 | | }}} |
226 | | |
227 | | == Uso de miembros de tipo Code == |
228 | | |
229 | | En OOP no se recomienda el uso de miembros que apunten a funciones asignables como pueden ser los punteros de funciones en C++ o los objetos de tipo Code en TOL. Una función asignable pretende recoger comportamientos polimórficos impredecibles y eso en OOP se trata mediante herencia de métodos virtuales. |
230 | | |
231 | | TOL dará un un mensaje de aviso cuando esto ocurra, aunque se permitirá su uso por si fuera necesario en casos extremos. |
232 | | |
233 | | En tales casos las funciones así utilizadas no tendrán acceso al ámbito de la clase pues no se trata de verdaderos métodos. |
234 | | |
235 | | Aún más peligroso resulta usar estos miembros de tipo Code dentro de un !NameBlock genérico, no instancia de clase, puesto que en ellos es imposible distinguir si fue creado como método o como objeto, por lo que tendrá acceso al ámbito del !NameBlock y sólo debería ser asignado a verdaderos métodos del mismo, nunca a objetos externos. |
236 | | |
237 | | Especialmente dañino resultaría que una misma función externa fuera asignada a miembros de tipo Code de diferentes !NameBlock's no globales, o bien que esa función se usara además fuera de ellos, pues ello podría incluso ocasionar una caída de TOL. |