Re: ejemplo del sistema de objetos de glib



On Fri, 2007-05-04 at 10:28 -0400, Alejandro Valdes Jimenez wrote:
> Adjunto un ejemplo que hice de gobject para que alguien si tiene un
> tiempecito le de una miradita... quiero saber si est�ien
> implementado
> y si es un buen ejemplo.

Le ech�na mirada r�da, no soy experto en GObject, pero tengo algunos
comentarios, ojal�e sean �s:

- Para definir el tipo te conviene usar la macro G_DEFINE_TYPE(), ya que
  evita que escribas a mano la declaraci�e varias funciones y
  cabeceras que son siempre iguales. Ve la documentaci�obre esa macro
  y las otras relacionadas. 

- Los atributos p�os que definiste (nombre, edad) t�camente 
  ser� declarados de otra manera: como datos privados, y con   
  funciones _get_name/age (), _set_name/age (). Adem� si quieres
  utilizar 100% GObject, deber� instalar esas propiedades en la 
  clase. Para eso necesitar�:

  - Agregar una enumeraci�on todas las propiedades, para poder 
    asignarle a cada una un entero distinto:

  enum {
      PROP_NAME = 1,
      PROP_AGE
  };

  - En _class_init ():

    /* substituir las funciones set/get_property por defecto de la 
       clase padre por unas definidas en nuestra clase */

    g_object_class->set_property = my_object_set_property;
    g_object_class->get_property = my_object_get_property;

    /* ... */

    /* instalar una propiedad para guardar el nombre de la persona */ 
    g_object_class_install_property (gobject_class, 
				     PROP_NAME,
                                     g_param_spec_string ("name", 
	 			                          "Name",
                                                          "The name of the person",
                                                          "an�o",
                                                          G_PARAM_READABLE | G_PARAM_WRITEABLE));

   /* ... */


  Esta llamada lo que hace es instalar en tu clase una propiedad de
  lectura/escritura "name" de tipo string, con valor por defecto
  "an�o". Haces algo similar para la edad, pero usas 
  g_param_spec_int (). Haces lo mismo para cada una de las otras 
  propiedades p�as que quieras instalar.

  Todav�faltar�declarar las funciones set/get_property (). Estas se
  deben ver as�proximadamente:

  my_object_set_property (GObject *object,
                          guint    prop_id,
                          const GValue *value,
                          GParamSpec   *pspec)
  {
        MyObjectPrivate *priv = MY_OBJECT (object)->priv;

    switch (prop_id) {
        case PROP_NAME:
            /* guardar la propiedad en mi string privado */
            if (priv->name) {
                 g_free (priv->name);
            } 
            priv->name = g_strdup (g_value_get_string (value));
	    break;
        case PROP_AGE:
            priv->age = g_value_get_int (value);
            break;
	default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        }
    }

  
  my_object_get_property() es bastante similar, 

  my_object_get_property (GObject *object,
                          guint    prop_id,
                          const GValue *value,
                          GParamSpec   *pspec)
  {
        MyObjectPrivate *priv = MY_OBJECT (object)->priv;

        switch (prop_id) {
        case PROP_NAME:
          g_value_set_string (value, priv->name);
          break;
        case PROP_AGE:
          g_value_set_int (value, priv->age);
          break;
       default:
            /* warn again... */
        }
  }

- La declaraci�e m�dos usando punteros a funci�ue hiciste tiene 
  sentido exclusivamente si deseas que una clase heredada cambie la   
  manera de realizar la acci�ue dicho m�do har�por defecto, y 
  a��oder ejecutarla tu mismo. Si lo que deseas es escribir un
  simple m�do sin nada especial, que no sea reimplementable por las 
  clases heredadas, no necesitas agregar el puntero a funci�
  De todas maneras, nunca querr� que tus usuarios llamen a m�dos 
  usando directamente punteros a funciones. Tener algo como 

  my_object_print (MyObject *object) 
  {
     object->print_function (object);
  }

  Ser�ideal. As�ara los usuarios es transparente que la funci�aya
  sido reemplazada o no.

- La declaraci�e la estructura privada en un archivo separado 
  (-private.h) s�es �si vas a dividir el c�o de tu clase 
  en m�de un archivo. En caso contrario (como en tu ejemplo), bastar�  con declararla en el mismo archivo .c

Algunas cuestiones de estilo con respecto a tus m�dos:

- En vez de hacer las llamadas 

    obj = persona_main_app_new ();
    obj->agregar_persona (obj,"matias",1);

  Yo asignar�los valores de la persona directamente en el constructor:

    obj = persona_new ("mat�", 1);

  O tambi�

    obj = persona_new ();
    persona_set_age (obj, 1);
    persona_set_name (obj, "matias");

  O, si instalaste las propiedades a la GObject, podr� incluso hacerlo
  as�
    obj = persona_new ();
    g_object_set_property (obj, "age", 1);
    g_object_set_property (obj, "name", "matias");



- El nombre (PersonaMainApp) me suena familiar :-)


Eso ser� Espero te sean �s estos comentarios. Si quieres ver un
ejemplo completo de una clase escrita con GObject, que instala
propiedades, se�s, y tiene dos constructores, te recomiendo mirar los
archivos eog/src/eog-print-preview.[ch], que pueden servirte.

�Saludos y que te diviertas con GObject!

Claudio
-- 
Claudio Saavedra <csaavedra alumnos utalca cl>




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]