Programación Orientada a Objetos – Cómo Escribir una Clase

Este post es parte de una serie de artículos sobre POO y viene a continuación de Clase e Instancia.

Ahora que entendemos (más o menos) cómo funciona la teoría básica de la P.O.O. y sabemos acerca de la importancia de las clases, es momento para que veamos cómo sería la estructura de una clase.

Es importante tener en cuenta que cada lenguaje tiene, de acuerdo a su sintaxis, sus propias normas sobre cómo escribir clases. No será lo mismo en PHP que en AS2 o incluso AS3. Así que, primero, hablaremos en un sentido más general, para luego pasar a la práctica concreta. Para los efectos, usaremos como lenguaje de ejemplo Action Script 2.0.

Estructura de la Clase

Los elementos básicos de una clase se estructuran de la siguiente forma (más abajo definiremos cada elemento):

  1. Paquete al que pertenece la clase (package – sólo en AS3, en AS2 se incluye en la Definición de la Clase).
  2. Definición de la Clase (class – En AS2, si la clase está incluida en un paquete, se usa la sintaxis paquete.clase).
  3. Variables Internas (Son de uso interno de la clase, por lo que se restringe su uso fuera de ellas con la palabra clave private, así la variable miVar, de tipo numérico, podría definirse así:
    private var miVar:Number = 0;)
  4. Constructor de la Clase (excepto en el caso de las clases estáticas, pero de eso hablaremos en otro post).
  5. Propiedades, Métodos y Eventos de la Clase (no necesariamente en ese orden, pero es una buena forma de organizarlo).

Por supuesto, una clase bien hecha contiene además comentarios con información sobre la clase, la forma de usarla, su autor, etc. En este caso lo omitimos para concentrarnos en lo básico y no enredarnos más de lo estrictamente necesario.

Dicho esto, veamos los puntos nombrados arriba en una clase de ejemplo, para luego pasar a explicar los conceptos:

Clase en AS2

Para crear una nueva instancia de la clase Persona debemos importarla y luego instanciar con la palabra clave new, pasándole los parámetros que necesita:

import cesarfrick.Persona;
var cesar:Persona = new Persona("César", "Frick", 36);

Ahora expliquemos de qué se trata lo que hemos dicho:

Paquete:
Aunque podemos colocar nuestras clases en el mismo directorio donde se encuentra el archivo que los usará, siempre resulta más ordenado y eficiente clasificarlos en carpetas, donde podemos colocar aquellas clases que tienen un mismo propósito. Así podemos tener una carpeta llamada graph para clases de tipo gráfico, externalData para clases que conectan y/o procesan datos externos, etc. Estas carpetas son conocidas como paquetes.
Otra ventaja de usar paquetes (además de mantener nuestras clases ordenadas) es que nos permiten importar todas las clases que necesitemos de ellos con sólo una línea: import paquete.*, en vez de tener que hacer un import para cada clase. Si te preocupa que terminen importándose más clases de las que necesitas de ese paquete, no hay problema porque sólo se importarán las que sean necesarias y no las que no utilices en el código.
En algunos lenguajes, existen palabras reservadas para declarar el paquete al que pertenece una clase (como en el caso de AS3), en estos casos va primero la declaración del paquete y luego la de la clase. En AS3 sería de esta forma:

package nombreDelPaquete{
class NombreDeLaClase{
...
}
}

Clase:
La clase, propiamente dicha, se declara con la palabra clave class.

Hay un par de cosas que debemos tener en cuenta cuando creamos una clase:

  • No es obligatorio, pero por regla general -los entendidos lo llaman convención y es cuando todos se ponen de acuerdo en hacer algo de la misma forma (¡ja! como si tal cosa fuese posible. Errr… perdón, eso es otro tema)- los nombres de las clases siempre comienzan con mayúsculas.
  • Esto si es obligatorio: El archivo donde se encuentra la clase debe tener el mismo nombre que ésta, respetando mayúsculas y minúsculas. Esto es importante porque los import usan el nombre del paquete (si lo hubiere) y la clase para ubicarlos en el disco, así que si usas diferentes nombres, nunca los hallará y dará error.
  • Si el lenguaje no tiene una palabra reservada para definir el paquete (AS2, por ejemplo), la definición de la clase sería así:

    class nombreDelPaquete.NombreDeLaClase{
    ...
    }

Variables Internas o Privadas:
En último término, todas las propiedades de una clase son en realidad variables, pero no es conveniente que el usuario de la clase pueda manipular directamente estas variables, por ello se mantienen privadas, es decir, sólo pueden llamarse y manipularse dentro del código de la clase, pero no fuera de ellas (o sea que si se trata de llamar a una de estas variables desde la instancia, no funcionará). Para hacer que una variable/función sea privada, se le antepone la palabra private.
Constructor:
Es la función que se ejecuta cada vez que se crea una instancia de la clase, Si necesitamos que nuestra clase inicie con ciertos valores, colocamos los parámetros correspondientes entre los paréntesis. La función constructora siempre devuelve Void (Vacío).
También puede haber casos en los que no queramos que la clase constructora ejecute ningún código. Para ello simplemente la colocamos vacía, es decir, la declaramos pero no ponemos código en ella. Si una clase no tiene un constructor, no puede ser instanciada.
Propiedades, Métodos y Eventos de la clase:
Decíamos antes que las propiedades son realmente variables dentro de la clase, pero para poder controlar qué puede cambiar o no el usuario de la clase, si los valores son correctos, etc. hacemos uso de unas funciones especiales para definir propiedades: get y set.

  • get permite al usuario recuperar el valor de la propiedad, leerlo, por lo que su salida debe ser correspondiente con la que se espera de la propiedad (por ejemplo, no tendría sentido que la propiedad “nombre” del ejemplo devolviese un número). Si sólo creamos una función get para una propiedad, ésta es de sólo lectura.
  • set es usado para darle un valor a la propiedad, normalmente se añaden aquí los controles para asegurarse que el valor que se asigna es del tipo deseado (y evitar que la clase colapse por un error de tipo de datos). La función de set, al ser para escribir en la propiedad no devuelve ningún tipo de datos, pero debe tener un parámetro que es el valor que se pasará a la variable. Al contrario de get, no puede haber una clase de sólo escritura (después de todo, no tiene ningún sentido tener una propiedad a la que se le pueda asignar un valor pero este no pueda ser recuperado).
  • Los métodos no son más que funciones públicas, que pueden tener o no datos y que afectan a la instancia de alguna forma.
  • Los eventos, al igual que los métodos, son funciones, pero estos reaccionan ante alguna interacción del usuario o pueden ser reescritos por éste. A ellos dedicaremos un post especial.

Bien, como ven escribir una clase no es tan complicado como puede pensarse en un principio. Luego hablaremos de las ventajas/desventajas de usar clases, pero por ahora creo que ha sido bastante (al menos yo estoy exhausto😛 ). Sólo decir que si les resulta muy complicado lo que ven acá, repasen los posts anteriores (seee, he tardado mucho en escribir éste) para que lo vean en contexto. También decir que en este caso y todos los que vengan escribiremos el código siguiendo las reglas del Strict Data Typing (Tipeo Estricto de Datos), al que le daremos unas líneas en el próximo post.

Technorati Tags: , ,


23 thoughts on “Programación Orientada a Objetos – Cómo Escribir una Clase

  1. Sublime. Esta genial

    oye, cuando dices lo de: “Si una clase no tiene un constructor, no puede ser instanciada.” Te refieres a hacer esto, ¿no?:

    import cesarfrick.Persona;
    var cesar:Persona = new Persona(”César”, “Frick”, 36);

    Es así? ¿eso es instanciarla?

  2. Excelente como de costumbre, de nuevo quedo esperando un nuevo post al respecto empezaré a programar mis propias clases!

    Bleend, cuando una clase no tiene constructor precisamente no tienes que instanciarla, puedes usar sus metodos directamente!

  3. Muchas gracias de nuevo por los comentarios. Espero que el próximo post no tarde tanto como éste😛
    @Bleend: Realmente la primera línea lo que hace es importar la clase. Al importarla, te evitas tener que escribir toda la dirección de la clase cada vez que quieres usarla. La segunda línea es la instanciación propiamente, que lo explico en en el post anterior.
    Si no importases previamente la clase, tendrías que instanciarla de esta forma:
    var pAlguien:cesarfrick.Persona = new cesarfrick.Persona("Nombre", "Apellido", 15);
    El import sólo se coloca una vez (por cada clase que importes) y debe ser la primera línea del código.
    @Alrevez: Muy cierto, si una clase no tiene constructor no tienes que instanciarla para poder usarla (como, por ejemplo, la clase Math en Action Script) pero debes tener en cuenta que sólo puede tener elementos estáticos. Luego hablaremos de ello con más calma.

  4. El método Math emplea el patrón Singleton si no me equivoco ¿verdad? A lo que me lleva a preguntar ¿vas a profundizar en patrones? ¿donde te envío las flores?
    Un saludo

  5. @cavabaja: jajajajajajaja. Gracias, pero prefiero que me envíes los dólares, ya me arreglo yo con las flores😉
    No, la clase Math no usa Singleton, porque este patrón está diseñado para evitar la creación de más de una instancia de la clase, pero cuando los elementos de la clase son estáticos no es necesaria su instanciación. En el caso de la clase Math (que consiste en una serie de métodos), sólo hay una serie de operaciones matemáticas, por lo que basta declararlas estáticas para hacer innecesaria la instanciación.
    Sí, espero que hablemos de patrones, aunque no creo que por lo pronto porque nos queda aún tela por cortar antes de llegar allí. De todas maneras, hablaremos antes de elementos estáticos y clases estáticas. En cualquier caso, para un nivel más profundo de programación en Action Script, yo recomiendo sin duda el blog del Maestro Zen, Zguillez, que no tiene pérdida: http://www.codigoactionscript.org/

  6. Felicidades, te quedo de lujo! ^^

    @Bleend: te pondré un ejemplo así lo captas más rápido.

    En un nuevo archivo Flash, crea un clip de película, ponle un nombre y dentro, en su 1er fotograma pega esto:


    // Uso de la clase "Delegate" sin instanciarlo
    function saluda(){
    return 'Hola '+this;
    }
    var saludaClip = saluda;

    import mx.utils.Delegate;
    var saludaRoot = Delegate.create(_root,saluda);

    trace( saludaClip() );
    trace( saludaRoot() );

    Tendrás el clip nuevo en el escenario, suponiendo que se llame “miClip”, lo ejecutamos.
    En el panel de salida tendremos:
    Hola _level0.miClip
    Hola _level0

    Es un ejemplo rápido del uso de la Clase Delegate y para acceder a su función “create” no tuvimos la necesidad de instanciar la clase con “new” .

    Pero esta Clase también puede instanciarse:


    // Uso de la clase "Delegate" instanciándola
    function saluda(){
    return 'Hola '+this;
    }
    var saludaClip = saluda;

    import mx.utils.Delegate;
    var d:Delegate = new Delegate(saluda);
    var saludaRoot = d.createDelegate(_root);

    trace( saludaClip() );
    trace( saludaRoot() );

    Según como hayas desarrollado la clase tendrás más opciones, y que mejor si esta preparada para todos sus posibles usos ^^ .

  7. Recuerdo que cuando me lo explicó el profesor de programación tardé 5 minutos para procesar la idea y responderle “no entendí un c…!”. Desde entonces evito utilizar clases cuando puedo.

    Y lo de las convenciones es peor que una suegra. Recuerdo que mi primer profesor de programación nos insistía que hagamos
    if(){

    para tener menos líneas, y desde el cuatrimestre siguiente todos los profesores hacían
    if()
    {

    Así que me quedó la costumbre de poner todo en una línea.

    1. Hola, Rebeca.
      Muchas gracias por el cumplido, la verdad es que yo también lamento no haber escrito te nuevo desde hace mucho y lo extraño. Lamentablemente las circunstancias no me lo han permitido.
      Sin embargo, si todo sale bien, espero estar escribiendo de nuevo muy pronto.
      Me alegra saber que esto te haya servido de alguna ayuda

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s