miércoles, marzo 29, 2006

Principio de encapsulamiento

En programación orientada a objetos, el encapsulamiento consiste en poder elegir qué información de un objeto es publicada y cuál forma parte de su estado, no siendo esta última accesible entre objetos.

Esta definición se podría identificar como la definición pura de lo que en POO es el encapsulamiento, sin embargo, en la realidad no siempre es así. Por ejemplo, en java todo el comportamiento es el esperado, en cambio, en C# la cosa cambia.

Por ejemplo, en el siguiente código java, tenemos una clase BaseClass la cual contiene un campo privado y método público a través del cual se puede acceder a dicho campo.

public class BaseClass {

private int _cont = 0;

private ExtendClass bClass = new ExtendClass ();

public int Cont() {

return _cont;

}

public int ParentCont() {

return bClass.Cont();

}

}


En la siguiente clase, heredamos de BaseClass y sobrescribimos el método Cont.

public class ExtendClass extends BaseClass{

public int Cont() {

return 3;

}

}


Dentro del método ParentCont de la BaseClass accedemos a una instancia previamente creada de ExtendClass , y lo hacemos a través de su método público ParentCont, en ningún momento se nos ocurriría acceder al campo privado, ya que rompería con el encapsulamiento.

Sin embargo, en C# no ocurre lo mismo que en Java. Es decir, en C# podríamos acceder al campo privado (bClass._cont), lo cual en mi opinión no me parece correcto. Tampoco entiendo la razón para romper con el paradigma de la programación orientada a objetos de ese modo.


3 comentarios:

Anónimo dijo...

Buenas. Me parece que te equivocas. Un miembro privado de una clase no puede ser accedido por las clases derivadas de esta. Si el miembro fuese público o protegido si lo podría ser.
¿Realmente has probado esto?

Cristóbal dijo...

Como digo, en C# ocurre y lo he probado, además contrastado con varios compañeros.

Si quieres más pruebas, te diré que las clases del ejemplo heredan de System.Windows.Forms.Panel y en ejecución una instancia de la clase hija contiene una instancia de la clase madre.

Corrito dijo...

Voy a poner un pequeño ejemplo de como modificar una variable privada de intancia(supuestamente privada SOLO para esa instancia, esa es la cuestion). Para pegar directamente en un cs.

---------------------------------
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace WindowsApplication25
{

public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button button1;
private System.ComponentModel.Container components = null;

public Form1()
{
InitializeComponent();
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(56, 64);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(376, 23);
this.button1.TabIndex = 0;
this.button1.Text = "Pulsame y luego mira el código";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(488, 141);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Como modificar variables privadas de instancia desde C#";
this.ResumeLayout(false);

}

[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private class Coche
{
private int velocidad = 0;
protected int VelocidadBase
{
get
{
return velocidad;
}
}
public void ModificaVelocidad(Ferrari coche, int value)
{
coche.velocidad = value;
}
public void ModificaVelocidad(Seiscientos coche, int value)
{
coche.velocidad = value;
}
}
private class Seiscientos : Coche
{
int i = 10;
public int Velocidad
{
get
{
return base.VelocidadBase + i;
}
}
}
private class Ferrari : Coche
{
int i = 100;
public int Velocidad
{
get
{
return base.VelocidadBase + i;
}
}
}

private void button1_Click(object sender, System.EventArgs e)
{

Seiscientos seiscientos = new Seiscientos();
Ferrari ferrari = new Ferrari();

MessageBox.Show("Alguien sabe como un Seiscientos puede dejar a un Ferrari a 1 Km/h??");

MessageBox.Show(String.Format("Velocidad de seiscientos: {0}\nVelocidad de Ferrari: {1}", seiscientos.Velocidad, ferrari.Velocidad));

seiscientos.ModificaVelocidad(ferrari, -99);

MessageBox.Show(String.Format("Velocidad de seiscientos: {0}\nVelocidad de Ferrari: {1}\nBy Bill Gates", seiscientos.Velocidad, ferrari.Velocidad));
}
}
}

-------------------------------