Programacion Orietada a Objeto avanzada con xHarbour y Xailer (III).

3.- Contruyendo una Clase en xHarbour (y Xailer).

Vamos a estudiar ahora como se contruye una clase en xHarbour y Xailer. Una Clase se compone de dos partes, por un lado la definición de la misma donde se indican los atributos y métodos a usar y por otro el desarrollo de cada método.

3.1 Definiendo una Clase

Veamos la sintaxis para la definicion de una clase:

CLASS <nombreClase> [FROM <superClase, …>]

[EXPORTED: | PROTECTED: | HIDDEN: ]

<declaración de miembros>
<…>

ENDCLASS

<nombreClase> Es el nombre que daremos a la clase que deseamos crear, por ejemplo Sujeto.

FROM indica de que Clases Padre heredará. xHarbour permite multiherencia, pero hay que dominar muy bien la construcción de clases para usarla.

<superClase, …> Nombres de las Clases Padre de las que hereda, separadas por coma.

EXPORTED: Hace que todos las variable y métodos definidos a continuación de esta palabra posean visibilidad total.

PROTECTED: Hace que todas las variables y métodos definidos a continuacuón de esta palabra sean solo visible por la propia clase y las que heredan de ella.

HIDDEN: Hace que todas las variable y métodos definidos a continuación de esta palabra sólo sean visibles por los métodos de la propia clase.

ENDCLASS indica que termina la definición de la clase.

3.1.1 Variables y métodos

Dentro de la definición de la clase incluiremos la declaración de  variables y métodos de la misma, veamos la sintaxis:

Para variables:

DATA <nombreVariable> [INIT <expresion>] [READONLY]

DATA indica que vamos a definir una variable

<nombreVariable> es el nombre de la variable que vamos a declarar.

INIT indica que vamos inicializar la variable con un valor por defecto

<expresion> indica la expresión (o el valor) inicial de la variable.

READONLY hace que la variable sea de sólo lectura y su valor sólo pueda modificarse desde los métodos de la propia clase.

Para métodos:

METHOD <nombreMetodo>[(<parámetros, …>)]

METHOD indica que vamos a definir un método.

<nombreMetodo> es el nombre del método que vamos a declarar.

<parámetros> sirve para indicar, opcionalmente, los parámetros que tiene este método.

3.2 Implementando métodos

Una vez definida la estructura de la clase, tendremos que implementar los métodos con el código que deberá ejecutar, para ello usaremos:

METHOD <nombreMetodo>[(<parámetros,…>)] CLASS <nombreClase>

<código a ejecutar>

RETURN <valorRetorno>

<nombreMetodo> es el nombre del método que vamos a desarrollar.

<parámetros> son los parámetros de este método. Aquí es obligatorio ponerlos si los lleva.

<nombreClase> es la clase a la que pertenece este método.

<código a ejecutar> son las intrucciones que deberá realizar el método.

<valorRetorno> es el valor que debe devolver el método. Siempre ha de retornar algo, en caso de que no devuelva nada, indicaremos nil.

3.2.1 Método constructor

Todas las clases que se definen en xHarbour y Xailer llevan implicito el método constructor de la misma, que como indica su nombre, es el que sirve para construir el Objeto. El método constructor por defecto es new() y se puede redefinir fácilmente. Tambien podemos indicar cualquier otro nombre de método como constructor incluyendo la palabra CONSTRUCTOR a finla de la declaración del método dentro de la defincion de la clase, por ejemplo:

METHOD new() CONSTRUCTOR

y lo implementaremos:

METHOD new() CLASS miClase

<operaciones de código>

RETURN self

Es importante y necesario indicar self en el RETURN del método contructor, ya que así es como xHarbour y Xailer toman refencia del nuevo objeto creado.

3.3 Consideraciones adicionales a la creación de Clases

Cuando creamos clases con xHarbour y Xailer debemos tener en cuenta algunas consideraciones adicionales:

  • Por defecto, todas las variables y métodos se crean EXPORTED:
  • No es necesario pero si conveniente indicar los paréntesis en los métodos que no contengan parámetros: new().
  • Una clase puede contener una variable que sea un objeto que haga referencia a otra clase.
  • Todas las variables se inician al valor nulo (nil) se no se indica lo contrario con INIT.
  • En xHarbour y Xailer no se especifica el tipo de dato, depende del valor que tome la variable.
  • Al definir en ámbito de variables de clase no olvidarse los dos puntos (:) de las palabrar reservaras EXPORTED:, PROTECTED: y HIDDEN:.

Además de estas consideraciones, yo propongo las siguiente:

  • Todas las variables de clase declararlas como PROTECTED:
  • Los valores de las variables de clases sólo se podrán cambiar mediante métodos de la misma clase, así, habrá que implementar métodos set() y get() para cada variable que sea accedida desde fuera del Objeto.
  • Todas las variables de clase internas (que se usen dentro de la clase y sólo dentro de ella) deberán declararse como HIDDEN:.
  • Las clases deben se independientes y no contener dentro de ellas código de acceso a datos (ni dbf’s, ni SQL, ni nada de nada). Ya estudiaremos como se hace el acceso a datos mediante una capa de persistencia.
  • Cuando dentro de una clase contengamos referencia a otra que sea un conjunto de datos (por ejemplo, las lineas de factura en una factura) usaremos una clase para contenr listas de objetos (en concreto la clase ArrayList).
  • Para recorrer un ArrayList usaremos una clase llamada ListIterator.

En las siguientes entregas definiremos un pequeño proyecto y empezaremos a trabajar definiendo clases. Veremos que son listas, como se implementan y como se recorren.

Anuncios

9 comentarios

  1. Gracias Jose Alfonso
    “clases independientes sin código de acceso … una capa de persistencia…” eso!
    Temas importantes si lo hay…
    Aguardo ansioso tu próximo artículo
    y te repito: gracias por compartirlo

  2. Me encuentro migrando una aplicacion de Clipper a (x)Harbour, y quisiera aplicar POO, para ello he seguido el ejemplo al crear una clase, sin embargo, me sale una serie de errores al hacerlo.. copio unas lineas para ver si me pueden dar una idea

    CREATE CLASS tEmpClass INHERIT OBJECT
    PROTECTED:
    DATA rut INIT “”
    EXPORTED:
    METHOD new(cRut) CONSTRUCTOR
    METHOD setRut(cRut)
    METHOD getRut()
    ENDCLASS

    METHOD setRut(cRut) CLASS tEmpClass
    ::rut := cRut
    RETURN nil

    METHOD getRut() CLASS tEmpClass
    RETURN ::rut

    los errors que me aparecen al compilar son los siguientes
    cgEmpClass.prg(10) Error E0030 Syntax error: “parse error at ‘CLASS'” //al Crear la Clase
    cgEmpClass.prg(11) Error E0020 Incomplete statement or unbalanced delimiters //Protected
    cgEmpClass.prg(12) Error E0030 Syntax error: “parse error at ‘RUT'” //al definir el Atributo RuT
    (Este se replica por cada Atributo)
    cgEmpClass.prg(30) Error E0020 Incomplete statement or unbalanced delimiters //EXPORTED
    cgEmpClass.prg(32) Error E0030 Syntax error: “parse error at ‘SETRUT'” //al Definir los Metodos de la Clase
    cgEmpClass.prg(33) Error E0030 Syntax error: “parse error at ‘GETRUT'”
    tambien para los demas metodos SET/GET de los Atributos

    los siguientes se repiten por cada implementacion de los metodos

    cgEmpClass.prg(104) Error E0030 Syntax error: “parse error at ‘SETRUT'”
    cgEmpClass.prg(105) Error E0001 Statement not allowed outside of procedure or function
    cgEmpClass.prg(106) Error E0001 Statement not allowed outside of procedure or function
    cgEmpClass.prg(108) Error E0030 Syntax error: “parse error at ‘GETRUT'”
    cgEmpClass.prg(109) Error E0001 Statement not allowed outside of procedure or function

    si me pueden ayudar, al correo laicoscj_amlg@latinmail.com

    ….

    • Hola Alvaro,

      Prueba así (quitando el CREATE):

      CLASS tEmpClass INHERIT OBJECT
      PROTECTED:
      DATA rut INIT “”
      EXPORTED:
      METHOD new(cRut) CONSTRUCTOR
      METHOD setRut(cRut)
      METHOD getRut()
      ENDCLASS

      METHOD setRut(cRut) CLASS tEmpClass
      ::rut := cRut
      RETURN nil

      METHOD getRut() CLASS tEmpClass
      RETURN ::rut

      Saludos

      José Alfonso Suárez Moreno

      • Estimado Jose:

        Gracias por tu respuesta, sin embargo, eso ya lo habia intentado antes de postear y tampoco funciono, no se si sera que la version de (x)Harbour sea incompatible, pues ademas reviso los fuentes que me envias y el codigo es igual (guardando la salvedad de que son los atributos y metodos que deseo utilizar)

      • Envíame el código fuente completo por e-mail.

        Saludos

        José Alfonso Suárez Moreno

  3. Solucionado, me falto #include “hbClass.ch”
    igual agradezco el tiempo que te has dado para ayudarme a resolver el problema

    un abrazo

    Alvaro

  4. llevo apenas una semana trabajando en xHarbour, y en las ayudas y ejemplos que encontre en ninguna parte salia que habia que agregar esa linea… igual el problema estaba entre el teclado y la silla…

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

A %d blogueros les gusta esto: