Noticias

¡RECUERDA QUE SI ERES UN NUEVO USUARIO, DEBES PRESENTARTE PARA PODER PUBLICAR MENSAJES! | TENEMOS CANAL OFICIAL DE TELEGRAM: t.me/unity3dspain

Ocultación de funciones de clase

Iniciado por iRobb, Agosto 26, 2015, 07:44:47 PM

Tema anterior - Siguiente tema
Hola a todos, os cuento.Quiero implementar unas clases en c# que serán polimórficas dependiendo de un nivel de acceso a las propiedades. Por ejemplo, una clase que solamente tiene acceso a propiedades que son de lectura, y otra clase que, además del acceso de lectura, tiene funciones de escritura. Manteniendo como máximas la reutilización de código y que las propiedades deben ser las mismas en las dos clases, solamente he llegado a la siguiente conclusión:public class cRead {  protected variable _v1;  public variable v1() {    return(_v1);  }}public class cReadWrite : cRead {  public void v1(variable v) {    _v1 = v;  }}Esto me permite instanciar a nivel de "usuario" la clase Read y a nivel de parametrización la clase ReadWrite, sin que el "usuario final" tenga acceso a funciones de escritura.A alguien se le ocurra otra manera de hacerlo, más práctica y/o elegante?Saludos


Pues imagina que tienes un inventario de cosas. Por un lado tienes un editor del inventario para añadir imágenes, nombres, etc. Por otro lado tienes la clase que se requiere para poder acceder al inventario, pero no editar las imágenes, ni textos ni nada de eso. Para evitar que el "usuario" (que es un programador) vea un montón de funciones de edición, que ni le sirven ni quieres que las tenga, le suministras la clase cRead. Sin embargo, si es el programador que tiene que hacer el editor del inventario, le suministras la clase cReadWrite.Por qué dices que no tiene sentido? 

Agosto 26, 2015, 09:40:56 PM #3 Ultima modificación: Agosto 26, 2015, 09:41:22 PM por kaito
El ejempo que has puesto, no tiene sentido porque se tendría que instanciar la clase cReadWrite(que te permite escribir) para crear la variable protegida _v1. Y tú lo que quieres es que el usuario no escriba o la modifique. Además, piensa que en la herencia de clases podemos acceder a las funciones de la clase base mediante una conversión explícita. Por lo que no creo que sea buen método. Sobre el ejemplo que has puesto sobre un inventario, lo que podrías hacer es crear una clase donde almacenar los datos(por ejemplo clase ITEM). Y a continuación creas una clase para acceder al item y otra clase para modificar el item, pero sin utilizar herencia de clases.

[quote author=kaito" data-ipsquote-contapp="forums" data-ipsquote-contenttype="forums" data-ipsquote-contentclass="forums_Topic" data-ipsquote-contentid="18779" data-ipsquote-contentcommentid="104797">El ejempo que has puesto, no tiene sentido porque se tendría que instanciar la clase cReadWrite(que te permite escribir) para crear la variable protegida _v1. Y tú lo que quieres es que el usuario no escriba o la modifique. Además, piensa que en la herencia de clases podemos acceder a las funciones de la clase base mediante una conversión explícita. Por lo que no creo que sea buen método. Sobre el ejemplo que has puesto sobre un inventario, lo que podrías hacer es crear una clase donde almacenar los datos(por ejemplo clase ITEM). Y a continuación creas una clase para acceder al item y otra clase para modificar el item, pero sin utilizar herencia de clases.[/quote]Desde luego que crear dos clases distintas con items iguales y repetir las funciones de la clase cRead en la cReadWrite no sería muy lógico. Eso si que no es muy OO y reutilizable.A ver, añado más código para que se vea mejor el proceso:public class cEditorInventario {  private cReadWrite readWrite = new cReadWrite()...  public cRead read() {  // Esto es totalmente factible y sin conversión explícita, sino implícita debido justamente a la herencia  return(r

Agosto 26, 2015, 10:40:17 PM #5 Ultima modificación: Agosto 26, 2015, 10:46:42 PM por kaito
Bueno, se me ha ocurrido lo siguiente. A ver que te parece:
using UnityEngine;
using System.Collections;

public class Test : MonoBehaviour {

public class Inventario{

   private int v1;

   public class Read{

      Inventario instancia;
      public int v1{ get{ return this.instancia.v1; } }

      public Read(Inventario instancia){

         this.instancia = instancia;

      }

   }

   public class ReadWrite{

      Inventario instancia;
      public int v1{ get{ return this.instancia.v1; }
         set{ this.instancia.v1 = value; } }


      public ReadWrite(Inventario instancia){

         this.instancia = instancia;

      }

   }

   public ReadWrite Editor;
   public Read Runtime;

   public Inventario(){

      this.Editor = new ReadWrite(this);
      this.Runtime = new Read(this);

   }

}

// Use this for initialization
void Start () {

   Inventario inventario = new Inventario();

   inventario.Editor.v1 = 15;
   Debug.Log(inventario.Runtime.v1);

}

}
 La clase Inventario contiene las variables y las clases Read(solo lectura, modo runtime) y ReadWrite(modo edición) que quedan conectadas sin utilizar herencia de clases, mediante una variable Inventario que paso en la construcción. Algo similar al sistema de componentes de Unity, que comparten un mismo GameObject.

Agosto 26, 2015, 11:06:32 PM #6 Ultima modificación: Agosto 26, 2015, 11:16:08 PM por iRobb
Si está bien, pero hay un problema porqué no puedes sobrecargar otras funciones. Si añades una función o un miembro en Read, tienes que añadirlo forzosamente en ReadWrite aunque hagas sencillamente un bypass. En mi código no:
public class cRead {
  protected int _elementosInventario;

    public int elementosInventario {
        get { return(_elementosInventario);
    }
}

public class cReadWrite : cRead {
    public new int elementosInventario {
        get { return(_elementosInventario);
        set { _elementosInventario = value;
    }
}

public class cEditorInventario {
  public cReadWrite _readWrite = new cReadWrite()...

      public cRead read() {
          // Esto es totalmente factible y sin conversión explícita, sino implícita debido justamente a la herencia
          return(_readWrite);
      }

    public cReadWrite readWrite {
           get { return(_readWrite); }
    }
}

public class cMostrarInventario {
    public cRead _read;

    public cMostrarInventario(cRead read) {
        this._read = read;
    }

    public cRead read {
        get { return(_read); }
    }
}


// Código general

// Pongo el acceso a Read y ReadWrite para que se vea el ejemplo, no para que
// se accediera
cEditorInventario ei = new cEditorInventario()...
ei.readWrite.elementosInventario = 5;

cMostrarInventario mi = new cMostrarInventario(ei.read());
int elementos = mi.read.elementosInventario;

En tu caso en cambio tendrías que añadir tanto el int como el get/set. Doble trabajo siempre que añades algo.     

Etiquetas: