Este sitio web usa cookies de terceros para analizar el tráfico y personalizar los anuncios. Si no está de acuerdo, abandone el sitio y no siga navegando por él. ×


6.5. Visibilidad

Nuestro ejemplo todavía no funciona correctamente: los atributos de una Puerta, como el "ancho" y el "alto" estaban declarados como "privados" (es lo que se considera en C# si no decimos lo contrario), por lo que no son accesibles desde ninguna otra clase, ni siquiera desde Porton.

Hemos manejado con frecuencia la palabra "public", para indicar que algo debe ser público, porque nuestras clases y su "Main" lo han sido siempre hasta ahora. Nos podríamos sentir tentados de declarar como "public" los atributos como el "ancho" y el "alto", pero esa no es la solución más razonable, porque no queremos que sean accesibles desde cualquier sitio, debemos recordar la máxima de "ocultación de detalles", que hace nuestros programas sean más fáciles de mantener.

Sólo querríamos que esos datos estuvieran disponibles para todos los tipos de Puerta, incluyendo sus "descendientes", como un Porton. Esto se puede conseguir usando otro método de acceso: "protected". Todo lo que declaremos como "protected" será accesible por las clases derivadas de la actual, pero por nadie más:

public class Puerta
{

    protected int ancho;     // Ancho en centimetros
    protected int alto;      // Alto en centimetros
    protected int color;     // Color en formato RGB
    protected bool abierta;  // Abierta o cerrada
  
    public void Abrir() 
    ...

Si quisiéramos dejar claro que algún elemento de una clase debe ser totalmente privado, podemos usar la palabra "private", en vez de "public" o "protected". En general, será preferible usar "private" a no escribir nada, por legibilidad, para ayudar a detectar errores con mayor facilidad y como costumbre por si más adelante programamos en otros lenguajes, porque puede ocurrir que en otros lenguajes se considere público (en vez de privado) un atributo cuya visibilidad no hayamos indicados

Así, un único fuente completo que declarase la clase Puerta, la clase Porton a partir de ella, y que además contuviese un pequeño "Main" de prueba podría ser:

// Ejemplo_06_05a.cs
// Portón, que hereda de Puerta, con "protected"
// Introducción a C#, por Nacho Cabanes

using System;

public class Ejemplo_06_05a
{

    public static void Main()
    {
        Puerta p = new Puerta();

        Console.WriteLine("Valores iniciales...");
        p.MostrarEstado();

        Console.WriteLine();

        Console.WriteLine("Vamos a abrir...");
        p.Abrir();
        p.SetAncho(80);
        p.MostrarEstado();

        Console.WriteLine();

        Console.WriteLine("Ahora el portón...");
        Porton p2 = new Porton();
        p2.SetAncho(300);
        p2.Bloquear();
        p2.MostrarEstado();
    }

}

// ------------------------------------------

// Puerta.cs
// Clases, get y set
// Introducción a C#, por Nacho Cabanes

public class Puerta
{

    protected int ancho;     // Ancho en centimetros
    protected int alto;      // Alto en centimetros
    protected int color;     // Color en formato RGB
    protected bool abierta;  // Abierta o cerrada

    public void Abrir()
    {
        abierta = true;
    }

    public void Cerrar()
    {
        abierta = false;
    }

    public int GetAncho()
    {
        return ancho;
    }

    public void SetAncho(int nuevoValor)
    {
        ancho = nuevoValor;
    }

    public void MostrarEstado()
    {
        Console.WriteLine("Ancho: {0}", ancho);
        Console.WriteLine("Alto: {0}", alto);
        Console.WriteLine("Color: {0}", color);
        Console.WriteLine("Abierta: {0}", abierta);
    }

} // Final de la clase Puerta   


// ------------------------------------------

// Porton.cs
// Clase que hereda de Puerta
// Introducción a C#, por Nacho Cabanes

public class Porton : Puerta
{

    bool bloqueada;

    public void Bloquear()
    {
        bloqueada = true;
    }

    public void Desbloquear()
    {
        bloqueada = false;
    }

    public new void MostrarEstado()
    {
        Console.WriteLine("Portón.");
        Console.WriteLine("Ancho: {0}", ancho);
        Console.WriteLine("Alto: {0}", alto);
        Console.WriteLine("Color: {0}", color);
        Console.WriteLine("Abierta: {0}", abierta);
        Console.WriteLine("Bloqueada: {0}", bloqueada);
    }

}

Ejercicios propuestos:

Ejercicio propuesto 6.5.1: Crea un proyecto a partir del ejemplo 06.05a, en el que cada clase esté en un fichero separado. Como podrás comprobar, ahora necesitarás un "using System" en cada fuente.
Ejercicio propuesto 6.5.2: Amplía las clases del ejercicio 6.4.2, creando un nuevo proyecto con las siguientes características: La clase Persona no cambia; la clase PersonaInglesa se modificará para que redefina el método "Saludar", para que escriba en pantalla "Hi, I am " seguido de su nombre; se creará una nueva clase PersonaItaliana, en el fichero "personaItaliana.cs", que deberá heredar las características de la clase "Persona", pero redefinir el método "Saludar", para que escriba en pantalla "Ciao"; crea también una clase llamada PruebaPersona3, en el fichero " pruebaPersona3.cs", que deberá contener sólo la función Main y creará un objeto de tipo Persona, dos de tipo PersonaInglesa, uno de tipo PersonaItaliana, les asignará un nombre, les pedirá que saluden y pedirá a la persona inglesa que tome té.
Ejercicio propuesto 6.5.3: Retoca el proyecto del ejercicio 6.4.3 (Libro): los atributos de la clase Documento y de la clase Libro serán "protegidos".
Ejercicio propuesto 6.5.4: Amplía el esqueleto del ConsoleInvaders (ejercicio 6.4.4): Amplía la clase Nave con un método "MoverDerecha", que aumente su X en 10 unidades, y un "MoverIzquierda", que disminuya su X en 10 unidades. Necesitarás hacer que esos atributos sean "protected". El método Lanzar de la clase Partida no esperará hasta el usuario pulse Intro sin hacer nada, sino que ahora usará un do-while que compruebe si pulsa ESC (para salir), o flecha izquierda o flecha derecha (para mover la nave: sus códigos son ConsoleKey.LeftArrow y ConsoleKey.RightArrow). Si se pulsan las flechas, la nave se moverá a un lado o a otro (con los métodos que acabas de crear). Al principio de cada pasada del do-while se borrará la pantalla ("Console.Clear();").
Ejercicio propuesto 6.5.5: Mejora el proyecto de la clase Coche (ejercicio 6.4.5): todos los atributos serán "protegidos" y los métodos serán "públicos".