Ejemplos de Clases en C#
Ejemplos de Clases en C# Ejemplo 1
Desarrollar un programa que tenga una clase que represente un Cuadrado y tenga los siguientes métodos: ingresar ingresar valor a su lado, imprimir su perímetro y su superficie.
using System; using System; using using System.Collections.Generic; using System.Linq; using System.Linq; using System.Text; using System.Text; namespace PruebaClase namespace PruebaClase { class Cuadrado { private int int lado; lado; //método Inicializar() public void void Inicializar() Inicializar() { Console.Write( Console .Write("Ingrese "Ingrese valor del lado:"); lado:" ); string linea; string linea; linea = Console Console.ReadLine(); .ReadLine(); lado = int int.Parse(linea); .Parse(linea); } //Método ImprimirPerimetro() public void void ImprimirPerimetro() { int perimetro; int perimetro; perimetro = lado * 4; Console.WriteLine( Console .WriteLine("El "El perímetro es:" + es:" + perimetro); } //Método ImprimirSuperficie() public void void ImprimirSuperficie() { int superficie; int superficie; superficie = lado * lado; Console.WriteLine( Console .WriteLine("La "La superficie es:" + es:" + superficie); } //Main() principal del programa static void void Main( Main(string string[] [] args) { Cuadrado cuadrado1 Cuadrado cuadrado1 = new Cuadrado Cuadrado(); (); cuadrado1.Inicializar(); //Llamando al método Inicializar(); cuadrado1.ImprimirPerimetro(); //Llamando al método ImprimirPerimetro(); cuadrado1.ImprimirSuperficie(); //Llamando al método ImprimirSuperficie(); Console.ReadKey(); Console .ReadKey(); } } }
Al ejecutar el código muestra el siguiente resultado
Ejemplo 2
Implementar la clase operaciones. Se deben ingresar los dos valores enteros, calcular su suma, resta, multiplicación y división, cada una en un método, e imprimir dichos resultados.
using System; using System; using using System.Collections.Generic; using System.Linq; using System.Linq; using System.Text; using System.Text; namespace PruebaClase namespace PruebaClase { class Operaciones { private int int valor1, valor1, valor2; // Método Inicializar() public void void Inicializar() Inicializar() { string linea; string linea; Console.Write( Console .Write("Ingrese "Ingrese primer numero:"); numero:" ); linea = Console Console.ReadLine(); .ReadLine(); valor1 = int int.Parse(linea); .Parse(linea); Console.Write( Console .Write("Ingrese "Ingrese segundo numero:"); numero:" ); linea = Console Console.ReadLine(); .ReadLine(); valor2 = int int.Parse(linea); .Parse(linea); } // Método Sumar() public void void Sumar() Sumar() { int suma; int suma; suma = valor1 + valor2; Console.WriteLine( Console .WriteLine("La "La suma es:" + es:" + suma); } //Método Restar() public void void Restar() Restar() { int resta; int resta; resta = valor1 - valor2; Console.WriteLine( Console .WriteLine("La "La resta es:" + es:" + resta); } // Método Multiplicar()
public void void Multiplicar() Multiplicar() { int multiplicacion; int multiplicacion; multiplicacion = valor1 * valor2; Console.WriteLine( Console .WriteLine("La "La multiplicación es:" + es:" + multiplicacion); } //Método Dividir() public void void Dividir() Dividir() { int division; int division; division = valor1 / valor2; Console.WriteLine( Console .WriteLine("La "La división es:" + es:" + division); } // Main() principal del programa static void void Main( Main(string string[] [] args) { Operaciones operacion1 = new Operaciones Operaciones(); (); operacion1.Inicializar(); // Llamando al método Inicializar(); operacion1.Sumar(); // Llamando al método Sumar(); operacion1.Restar(); // Llamando al método Restar(); operacion1.Multiplicar(); // Llamando al método Multiplicar(); operacion1.Dividir(); // Llamando al método Dividir(); Console.ReadKey(); Console .ReadKey(); } } }
Al ejecutar el código muestra el siguiente resultado
Publicado por Yhonatan por Yhonatan Robles Vega
CLASES Ejemplo básico:
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
using System; using System.Collections.Generic; System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; System.Threading.Tasks; namespace ConsoleApplication1 { public class ClaseBasica ClaseBasica { public int i = 10; } class Program { static void Main(string[] args) { object Objeto; Objeto = new ClaseBasica(); ClaseBasica(); ClaseBasica a; a = (ClaseBasica)Objeto; (ClaseBasica)Objeto; Console.WriteLine(a.i); ClaseBasica ClaseBasica b = new ClaseBasica(); ClaseBasica(); Console.WriteLine(b.i); Console.ReadLine(); } } }
Comparar cómo hemos creado el objeto “ a” y cómo el objeto “ b“, el resultado es el mismo pero el objeto “b” fue creado directamente a partir de la clase “ ClaseBasica” mientras que el objeto “a” fue creado a partir del objeto “Objeto“. Veamos el ejemplo anterior ampliado:
C#
1 2 3 4 5 6 7 8 9 10
using System; using System.Collections.Generic; System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; System.Threading.Tasks; namespace ConsoleApplication1 { public class ClaseBasica ClaseBasica
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 }
{ public int i = 10; //Campo private int tantoporcien; tantoporcien; //Campo //Campo public int TantoPorCien TantoPorCien //Propiedad { get { return tantoporcien; } set { if ((value >= 0) && (value <= 100)) { tantoporcien = value; } } } public void Resetea() Resetea() //Método { tantoporcien = 0; } } class Program { static void Main(string[] args) { object Objeto; Objeto = new ClaseBasica(); ClaseBasica(); ClaseBasica a; a = (ClaseBasica)Objeto; (ClaseBasica)Objeto; a.i += a.i; // Expresion lambda. Equivalente a "a.i = a.i + a.i"; a.TantoPorCien=70; Console.WriteLine(a.i); Console.WriteLine(a.TantoPorCien+"%"); a.Resetea(); Console.WriteLine(a.TantoPorCien Console.WriteLine(a.TantoPorCien + "%"); ClaseBasica ClaseBasica b = new ClaseBasica(); ClaseBasica(); b.i =+ b.i; // ojo esto simplemente simplemente asigna el signo signo del entero es decir no hace hace nada en este caso; caso; b.TantoPorCien = 75; b.TantoPorCien = 750; Console.WriteLine(b.i); Console.WriteLine(b.TantoPorCien Console.WriteLine(b.TantoPorCien + "%"); Console.ReadLine(); } }
Varias cosas a tener en cuenta, hemos ampliado la clase con un nuevo campo llamado llamado “tantoporcien“, además como se trata de un campo que requiere un control sobre su valor ya que queremos que su valor esté comprendido entre 0 y 100, lo declararemos como private de forma que sólo pueda ser manipulado a partir de propiedades (TantoPorCien) o métodos (Resetea). El resultado será:
C#
1 2 3 4 5
20 70% 0% 10 75%
Podemos mejorar nuestra clase implementando un método que imprima directamente directamente en pantalla “Imprime “: C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
... namespace ConsoleApplication1 { public class ClaseBasica ClaseBasica { ... public void Imprime() Imprime() { Console.WriteLine(this.i.ToString() Console.WriteLine(this.i.ToString() + " - " + this.tantoporcien.ToString()+"%"); } } class Program { static void Main(string[] args) { object Objeto; Objeto = new ClaseBasica(); ClaseBasica(); ClaseBasica a; a = (ClaseBasica)Objeto; (ClaseBasica)Objeto; a.i += a.i; // Expresion lambda. Equivalente a "a.i = a.i + a.i"; a.TantoPorCien=70; a.Imprime(); a.Resetea(); a.Imprime(); ClaseBasica ClaseBasica b = new ClaseBasica(); ClaseBasica(); b.i =+ b.i; // ojo esto simplemente simplemente asigna el signo signo del entero es decir no hace hace nada en este caso; caso; b.TantoPorCien = 75; b.TantoPorCien = 750; b.Imprime(); Console.ReadLine(); } } }
Propiedades autoimplemen autoimplementadas tadas Son una característica incluida a partir de la versión 3.0 de C# que hacen más concisa la declaración de una propiedad. Es posible aplicarla siempre que no exista “lógica” en los descriptores de acceso de la propiedad.
C#
1 public class Cliente Cliente { 2 private int idcliente; idcliente; 3 public int IdCliente IdCliente { 4 get {return id cliente;} 5 set {} 6 } 7 private string nombre; 8 public string Nombre { 9 get {return nombre;} 10 set {nombre = value;} 11 } 12 }
En el ejemplo anterior tenemos dos propiedades “IdCliente” y “Nombre”, la primera sólo de lectura. Veamos como quedaría si usáramos propiedades propiedades autoimplementadas. autoimplementadas.
C#
1 public class Cliente Cliente { 2 public int IdCliente IdCliente {get; private set;} set;} 3 public string Nombre {get; {get; set;} 4}
C#
1 using System; 2 using System.Collections.Generic; System.Collections.Generic;
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
using System.Linq; using System.Text; namespace ConsoleApplication1 { public class Cliente Cliente { public int IdCliente IdCliente { get; private private set; } public string Nombre { get; get; set; } public Cliente() { Nombre ="Vacio"; IdCliente = 33; } } class Program { static void Main(string[] args) { Cliente c1 = new Cliente(); Console.WriteLine(c1.Nombre); Console.WriteLine(c1.IdCliente.ToString()); c1.Nombre = "Pepe"; //c1.IdCliente = 66; daría error d e compilación porque es p rivate. Console.WriteLine(c1.Nombre); Console.ReadLine(); } } }
MSDN: Propiedades Autoimplementadas
Los constructores. Son métodos que llevan el mismo nombre que la clase y se ejecutan automáticamente cuando se crea el objeto. Al igual que otros métodos pueden estar sobrecargados. Veamos un ejemplo de una clase “Alumno” con dos campos, un constructor sobrecargado y un método. No devuelven ningún tipo, ni siquiera “void”. Nunca se le puede llamar de manera explícita en el código, únicamente únicamente implícitamente en la creación de una instancia de la clase. El constructor de una clase que no espera parámetro alguno es designado como “constructor por defecto” de la clase. Normalmente un constructor se encarga de la inicializaci inicialización ón de campos.
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
using System; using System.Collections.Generic; System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; System.Threading.Tasks; namespace ConsoleApplication1 { public class Alumno Alumno { private int edad; private string nombre; public Alumno() // Constructor Constructor por defecto { edad = 0; nombre = "Sin nombre"; } public Alumno(string p_nombre, int p_edad ) { edad = p_edad; nombre = p_nombre; } public void Imprime() Imprime() { Console.WriteLine("Alumno: Console.WriteLine("Alumno: "+ this.nombre + " - Edad: " + this.edad.ToString()+" this.edad.ToString()+" años."); } } class Program { static void Main(string[] args) { Alumno a = new Alumno(); Alumno b = new Alumno("Pedro",33); a.Imprime(); b.Imprime(); Console.ReadLine(); } } }
El resultado será:
C#
1
Alumno: Sin nombre - Edad: 0 años. 2
Alumno: Pedro - Edad: 33 años.
Ojo: si quisiéramos imprimir directamente el nombre o la edad de un alumno por ejemplo “Console.Write (a.nombre);” daría un error ya que se trata de un campo privado. Otro ejemplo:
C#
1 ... 2 public class Persona { 3 private string elApellido; elApellido; 4 private string elNombre; 5 private string laClave; laClave; 6 public string apellido apellido { 7 get { return el Apellido; } 8 set { elApellido=value.ToUpper();} elApellido=value.ToUpper();} 9 } 10 ... resto de propiedades ... 11 12 // Método constructor por defecto 13 public Persona() { 14 elApellido=""; 15 elNombre=""; 16 laClave="1234"; 17 } 18 // Sobrecarga del método constructor 19 public Persona (string apellido, apellido, string nombre, string clave) clave) { 20 elApellido = apellido; 21 elNombre = nombre; 22 laClave = clave; 23 }
Orden de llamada de los constructores Cuando se crean objetos de una clase derivada, antes de llamar a su constructor se llama a los constructores de la las clases base, empezando siempre por la más general y terminando por la más específica. Si añadimos en la clase derivada un constructor por defecto, debemos seguir algunas reglas:
Si el constructor de una clase derivada no invoca de forma explícita al constructor de la clase base (con la ayuda de la palabra reservada “base“), el constructor por defecto, si existe, lo hará de manera implícita. Si una clase base no ofrece constructor por defecto, la clase derivada debe hace una llamada explícita al constructor de la clase base usando la palabra reservada base. C#
1 ... 2 public class ClaseA ClaseA { 3 public ClaseA () { //Constructor por defecto defecto 4 Console.WriteLine("Constructor Console.WriteLine("Constructor de la clase A"); 5 } 6 } 7 8 public class ClaseA1: ClaseA1: ClaseA { 9 public ClaseA1 ClaseA1 () { //Constructor por defecto defecto 10 Console.WriteLine("Constructor Console.WriteLine("Constructor de la clase A1"); 11 } 12 } 13 ... 14 ... Main() { 15 ClaseA ObjA = new ClaseA(); 16 ClaseA1 ObjA1 = new ClaseA1(); 17 }
El resultado del programa será:
C#
1 Constructor de la clase A 2 Constructor de la clase A 3 Constructor de la clase A1
Veamos dos ejemplo ejemplo con la clase “Asalariado” que tendría tendría como clase base la clase “Persona”, ambos constructores tendrían el mismo efecto ya que la clase Persona sí tiene un constructor por defecto.
C#
1 public Asalariado(): base() base() { 2 elSalario =0; 3}
C#
1 public Asalariado() { 2 elSalario =0; 3}
Ahora podríamos añadir un constructor sobrecargado en la clase Asalariado:
C#
1 public Asalariado (string apellidostring apellidostring nombre, string clave, clave, decimal decimal salario) { 2 elApellido = apellido; 3 elNombre = nombre; 4 laClave = clave; 5 elSalario = salario; 6}
Aunque sería más correcto utilizar el constructor que ya existe en la clase Persona:
C#
1 public Asalariado ( apellido, apellido, string nombre, string clave, clave, decmial decmial salario) : base (apellido,nombre,clave (apellido,nombre,clave)) { 2 elSalario = salario; 3}
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
using System; using System.Collections.Generic; System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { public class Persona Persona { private string elApellido; elApellido; private string elNombre; elNombre; private string laClave; laClave; // Método constructor por defecto public Persona() { elApellido = ""; elNombre = ""; laClave = "1234"; }
21 22 // Sobrecarga del método constructor 23 public Persona(string apellido, apellido, string nombre, string string clave) 24 { 25 elApellido = apellido; 26 elNombre = nombre; 27 laClave = clave; 28 } 29 30 public string apellido apellido 31 { 32 get { return elApellido; } 33 set { elApellido = value.ToUpper(); } 34 } 35 36 } 37 public class Asalariado: Asalariado: Persona { 38 private decimal decimal elSalario; 39 public Asalariado(): Asalariado(): base() 40 { 41 elSalario = 0; 42 } 43 /*public Asalariado (string apellido, string nombre, string clave, decimal salario) { 44 elApellido = apellido; 45 elNombre = nombre; 46 laClave = clave; 47 elSalario = salario; 48 }*/ 49 public Asalariado Asalariado ( string apellido, string nombre, string clave, decimal decimal salario) salario) : base (apellido,nombre,clave) (apellido,nombre,clave) { 50 elSalario = salario; 51 } 52 } 53 54 class Program 55 { 56 static void Main(string[] args) 57 { 58 Asalariado A1 = new Asalariado("Pedraza", "Juanjo", "1234", 25000); 59 Console.ReadLine(); 60 } 61 } 62 }
Más sobre propieda propiedades: des: “get” y “set”. Sobre nuestra clase Alumno vamos a crear las propiedades que nos permitan cambiar la edad y el nombre a un objeto ya creado.
C#
1 using System;
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
using System.Collections.Generic; System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; System.Threading.Tasks; namespace ConsoleApplication1 { public class Alumno Alumno { private int edad; private string nombre; public Alumno() // Constructor Constructor por defecto { edad = 0; } public Alumno(string p_nombre, int p_edad ) { edad = p_edad; nombre = p_nombre; } public int Edad { get { return edad; } set { edad = value; } } public string Nombre { get { return nombre != null ? no mbre : "Sin nombre"; } } public void Imprime() Imprime() { Console.WriteLine("Alumno: Console.WriteLine("Alumno: "+ this.Nombre + " - Edad: " + this.Edad.ToString()+" años."); } } class Program { static void Main(string[] args) { Alumno a = new Alumno(); Alumno b = new Alumno("Pedro",33); a.Imprime(); b.Imprime(); Console.ReadLine(); } } }
El resultado será el mismo que antes.
Miembros estáticos (static) o compartidos: Se trata de una especie de campo común a todos los objetos de la clase. El siguiente ejemplo muestra como poder llevar un contador de los objetos Alumnos creados, para ello crearemos el campo “contador” y la propiedad “Contador” “Contador” ambas con la la propiedad “static”. “static”. Los miembros miembros compartidos o estático son campos, propiedades o métodos a los que pueden acceder todas las instancias de una clase. Bien muy bien cuando cuando queremos gestionar datos que no son específicos de una instancia de clase sino de la propia clase.
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
using System; using System.Collections.Generic; System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; System.Threading.Tasks; namespace ConsoleApplication1 { public class Alumno Alumno { private static static int contador; private int edad; private string nombre; private int matricula; matricula; public static int Contador { get { return contador; } } public Alumno() // Constructor Constructor por defecto { edad = 0; contador = ++contador; matricula = contador; } public Alumno(string p_nombre, int p_edad ) { edad = p_edad; nombre = p_nombre; contador = ++contador; matricula = contador; } public int Edad { get { return edad; } set { edad = value;
41 } 42 } 43 public string Nombre 44 { 45 get 46 { 47 return nombre != null ? no mbre : "Sin nombre"; // condición ? cierto : falso 48 } 49 } 50 51 public void Imprime() Imprime() 52 { 53 Console.WriteLine("Nro.:"+matricula Console.WriteLine("Nro.:"+matricula.ToString()+" .ToString()+" de "+Contador.ToString()+" | Alumno: "+ this.Nombre + " 54 - Edad: " + this.Edad.ToString()+" años."); 55 } 56 57 } 58 59 class Program 60 { 61 static void Main(string[] args) 62 { 63 Console.WriteLine("Total Console.WriteLine("Total alumnos antes:" + Alumno.Contador.ToString()); 64 Alumno a = new Alumno(); 65 Alumno b = new Alumno("Pedro",33); 66 Console.WriteLine("Total Console.WriteLine("Total alumnos después:" + Alumno.Contador.ToString()); 67 a.Imprime(); 68 b.Imprime(); 69 Console.ReadLine(); 70 } 71 } }
La salida sería:
C#
1 2 3 4
Total alumnos antes:0 Total alumnos después:2 Nro.:1 de 2 | Alumno: Sin no mbre - Edad: 0 años. Nro.:2 de 2 | Alumno: Pedro - Edad: 33 años.
Ojo esto no está permitido permitido::
C#
1 ... 2 public static int int Contador
3 { 4 get { return contador; } 5 set { contador = value; } 6 } 7 ... 8 a.Contador=100;
Daría error porque la utilización de un miembro compartido mediante un instacia de la clase está prohibida.
Como acceder a una propiedad de una clase base A veces un objeto hijo necesita acceder a un campo o propiedad de la clase base de la cual desciende.
Por ejemplo una asignació asignación: n: ((ClasePadre)ObjetoHijo).Propiedad ((ClasePadre)ObjetoHijo).Propiedad = Valor;
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
using System; using System.Collections.Generic; System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; System.Threading.Tasks; namespace ConsoleApplication1 { public class Padrino { private string nombre; public string Nombre { get { return nombre; } set { nombre = value; } } } // Herencia: "Alumno" hereda todo de la clase "Padrino", no obstante los campos declarados como private // sólo son accesibles en la clase donde fueron declarados. public class Alumno Alumno : Padrino { private static static int contador; private int edad; private string nombre; private int matricula; matricula; public static int Contador { get { return contador; } }
30 public Alumno() // Constructor Constructor por defecto 31 { 32 edad = 0; 33 contador = ++contador; 34 matricula = contador; 35 } 36 public Alumno(string p_nombre, int p_edad ) 37 { 38 edad = p_edad; 39 Nombre = p_nombre; 40 contador = ++contador; 41 matricula = contador; 42 } 43 public int Edad 44 { 45 get 46 { 47 return edad; 48 } 49 set 50 { 51 edad = value; 52 } 53 } 54 // Redefinimos "new" 55 public new string Nombre Nombre 56 { 57 get 58 { 59 return nombre != null ? no mbre : "Sin nombre"; 60 } 61 set { nombre = value + ", ( alumno)"; } 62 } 63 64 public void Imprime() Imprime() 65 { 66 Console.WriteLine("Nro.:"+matricula Console.WriteLine("Nro.:"+matricula.ToString()+" .ToString()+" de "+Contador.ToString()+" | Alumno: "+ this.Nombre + " 67 - Edad: " + this.Edad.ToString()+" años."); 68 } 69 70 } 71 72 class Program 73 { 74 static void Main(string[] args) 75 { 76 Console.WriteLine("Total Console.WriteLine("Total alumnos antes:" + Alumno.Contador.ToString()); 77 Alumno a = new Alumno(); 78 a.Nombre = "María"; 79 ((Padrino)a).Nombre = "Luciana"; 80 a.Edad = 23; 81 Alumno b = new Alumno("Pedro",33); 82 ((Padrino)b).Nombre = "Ramón"; 83 Console.WriteLine("Total Console.WriteLine("Total alumnos después:" + Alumno.Contador.ToString()); 84 a.Imprime(); 85 Console.WriteLine("Padrino: Console.WriteLine("Padrino: {0}",((Padrino)a).Nombre); 86 b.Imprime(); 87 Console.WriteLine("Padrino: Console.WriteLine("Padrino: {0}", ((Padrino)b).Nombre); 88 Console.ReadLine(); 89 } 90 } }
El resultado sería:
C#
1 2 3 4 5 6
Total alumnos antes:0 Total alumnos después:2 Nro.:1 de 2 | Alumno: María, (alumno) - Edad: 2 3 años. Padrino: Luciana Luciana
Nro.:2 de 2 | Alumno: Pedro, (alumno) - Edad: 33 años. Padrino: Ramón
Destructor de un objeto: Los destructores son otros métodos particulares de una clase. Llevan el mismo nombre de la clase precedida del signo “~” (Alt+126) y no pueden llevar ningún parámetro, por lo que no puede haber más de de un destructor, es decir no permite la sobrecarga. sobrecarga.
C#
1 ~Alumno() //Destructor del objeto Alt+126 2 { 3 //Libera memoria y cierra archivos abiertos automáticamente 4 ... código liberación de memoria .... 5 ... código cierre de archivos ... 6 ... código cierre de conexión con base d e datos ... 7 }
Declaración “protected”. Cuando definimos un campo, propiedad o método como “public”, está será accesible desde cualquier sitio. Si la declaramos como “private” sólo es accesible en la clase donde está definida, si una clase hereda de otra campos, propiedades o métodos privados, está clase tampoco podrá acceder a los campos, propiedades o métodos de la clase heredada. Para solucionar esto se utiliza utiliza la declaración “protected” que permite que una clase “hija” pueda acceder a los métodos de su clase “padre”, sin que estos sean accesibles desde otros sitios. Arrays de objetos Muchas veces necesitamos necesitamos crear más de un objeto de la misma clase para ello, imaginemos un equipo de fútbol, podríamos podríamos crear 11 objetos j1, j2, j3 etc. o bien un array de 11 objetos.
C#
1 2 3 4 5 6
... Main() ... ClaseJugador[] Jugadores = new ClaseJugador[11]; for (byte i = 0; i < 11; i++) Jugadores[i] = new ClaseJugador(); // Constructor ...
Ahora bien imaginamos que tenemos la clase: “ClaseJuagador” pero que a partir de ella hemos creado 2 nuevas clases “ClasePortero” y “ClaseJugadorCampo” para este caso también nos serviría un array y podría quedar de la siguiente forma:
C#
1 2 3 4 5 6 7
... Main() ... ClaseJugador[] Jugadores = new ClaseJugador[11]; Jugadores[0] = new ClasePortero(); // Constructor for (byte i = 1; i < 11; i++) Jugadores[i] = new ClaseJugadorCampo(); // Constructor ...
Funciones Virtuales: “override”. Siguiendo con el ejemplo del equipo de futbol, si en vez de un constructor tenemos un método llamado “Jugar”:
C#
1 public class ClaseJugador ClaseJugador { 2 public void Jugar() { 3 Console.WriteLine("Estoy Console.WriteLine("Estoy jugando!"); 4 } 5 } 6 7 public class ClasePortero: ClasePortero: ClaseJugador { 8 public new void Jugar() { 9 Console.WriteLine("Estoy Console.WriteLine("Estoy jugando con las manos!"); 10 } 11 } 12 13 public class ClaseJugadorCampo: ClaseJugadorCampo: ClaseJugador ClaseJugador {
14 public new void Jugar() { 15 Console.WriteLine("Estoy Console.WriteLine("Estoy jugando con los pies!"); 16 } 17 }
Si ejecutamos:
C#
1 2 3 4 5 6 7 8 9
... ClaseJuagador ObjJugador = new ClaseJuagador(); ClasePortero ObjPortero = new ClasePortero(); ClaseJuagadorCampo ClaseJuagadorCampo ObjJugadorCampo = n ew ClaseJuagadorCampo(); ... ObjJugador.Jugar(); ObjPortero.Jugar(); ObjJugadorCampo.Jugar(); ...
Saldrá correctamente:
C#
1 Estoy juagando! 2 Estoy jugando con las manos! 3 Estoy jugando con los pies!
Pero por otro lado si creamos un array:
C#
1 2 3 4 5 6 7 8
ClaseJugador[] Jugadores = new ClaseJugador[11]; Jugador[0] = new ClasePortero(); Jugador[1] = new ClaseJugadorCampo(); Jugador[2] = new ClaseJugador(); Jugador[0].Jugar(); Jugador[1].Jugar(); Jugador[2].Jugar();
Todos darán la misma respuesta a pesar de que cada elemento del array es una clase distinta.
Ejemplo de una clase “ClaseCuadro “: Propiedades, Métodos y Eventos . La clase está compuesta por Campos, Propiedades, Campos y propiedades : aunque para el usuario de un objeto los campos son similares a las propiedades , estas últimas modifican u obtienen los valores de los campos mediante los descriptores de acceso get y set. Los campos deberán ser declarados como privados (private) si queremos asegurarnos que su valor sea controlado por el código de las propiedades. Métodos y eventos: Los métodos nos permiten comunicarnos con los objetos que componen una aplicación, pero los objetos también tienen la posibilidad de transmitirnos sus reacciones generando eventos. En el diseño de la interfaz gráfica de una aplicación ya que nos permite obtener datos relativos a las acciones efectuadas por el usuario.
OBJETOS Instanciar las clases.
1. Declaración de una variable que permita el acceso al objeto 2. Creación del objeto C#
1 Persona p; // Paso 1 2 ... 3 p = new Persona(); // Paso 2 4 ...
Podemos combinar combinar ambas operaciones en una única línea:
C#
1 Persona p = new Persona();
Para utilizar otro constructor deberemos especificar la lista de parámetros y en función del tipo new w llamará al constructor correspondiente: y número de parámetros el operador ne correspondiente: C#
1 P ersona p = new Persona("Pedraza","Juanjo","1234"); Persona("Pedraza","Juanjo","1234");
Inicialización de una instancia instancia a la vez que es creada:
C#
1 2 3 4 5
Persona p = new Persona { apellido = "Pedraza", nombre="Juanjo", clave="1234" };
Esto sería lo mismo que hacer:
C#
1 Persona p; 2 p = new Persona(); 3 p.apellido = "Pedraza"; "Pedraza"; 4 p.nombre="Juanjo"; 5 p.clave="1234";
Inicialización de una colección
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
using System; using System.Collections.Generic; System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; System.Threading.Tasks; namespace ConsoleApplication1 { public class Persona Persona { public string Apellido; Apellido; public string Nombre; public string Clave; Clave; } public class Personilla Personilla : Persona { public int Edad; } public class Animal Animal { public string apodo; } class Program { static void Main(string[] args) { Persona p1 = new Persona { Nombre = "Juanjo", Apellido = "Pedraza", Clave = "1234" }; Animal a1 = new Animal { apodo = "Chucho" }; // Lista de objetos List
ListaPersonas = new List { new Persona { Nombre = "Juanjo", Apellido = "Pedraza", Clave = "1234"}, new Persona { Nombre = "Juan", Apellido = "Martínez", Clave = "1234"}, new Persona { Nombre = "Carla", Apellido = "López", Clave = "12 34"}, new Persona { Nombre = "Laura", Apellido = "Carreguí", Clave = "1234"}, new Personilla { Nombre = "Ramón", Apellido = "Ferrandis", Clave = "1234", Edad=33}, };
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 } 73 } 74 }
//Array de Personas var ArrayPersonas = new[] { new Personilla { Nombre = "Ramón", Apellido = "Ferrandis", Clave = "1234", Edad=33}, new Persona { Nombre = "Juanjo", Apellido = "Pedraza", Clave = "1234"}, new Persona { Nombre = "Juan", Apellido = "Martínez", Clave = "1234"}, new Persona { Nombre = "Carla", Apellido = "López", Clave = "12 34"}, new Persona { Nombre = "Laura", Apellido = "Carreguí", Clave = "1234"} }; //Array de animales var ArrayAnimales = new[] { new Animal { apodo = "Chucho" }, // new Personilla o new Persona daría error porque no pertenece a la clase Animales ... }; //Array de objetos - otra opción Persona[] ArrayPersonas2 = { new Persona { Nombre = "Juanjo", Apellido = "Pedraza", Clave = "1234"}, new Persona { Nombre = "Juan", Apellido = "Martínez", Clave = "1234"}, new Persona { Nombre = "Carla", Apellido = "López", Clave = "12 34"}, new Persona { Nombre = "Laura", Apellido = "Carreguí", Clave = "1234"}, new Personilla { Nombre = "Ramón", Apellido = "Ferrandis", Clave = "1234", Edad=33} }; Console.WriteLine(p1.Apellido); Console.WriteLine(ListaPersonas[1].Apellido); Console.WriteLine(ArrayPersonas[2].Apellido); Console.WriteLine(ArrayPersonas2[3].Apellido); Console.WriteLine(ArrayPersonas2[4].Apellido); Console.ReadKey();
Destrucción de una instancia La destrucción es automática, el CLR (common (common Language Runtime) vigila que todas las instancias sean accesibles (es decir que existan para la aplicación), si no encuentra ningún medio para acceder a ella el objeto queda marcado como huérfano y cuando la memoria de la Collector (Recolector aplicación decrezca entonces el G arbage Collector (Recolector de basura) intervendrá y eliminará los objetos huérfanos. Es durante este proceso cuando los destructores de cada uno de los objetos. Es posible forzar el Garbage Collector, pero es un trabajo relativamente relativamente costoso que hay que utilizar con precaución:
C#
1 GC.Collect(); GC.Collect();
6.2. Objetos y clases en C# Curso: Programación Curso: Programación en C# (2015), por Nacho Cabanes
6.2. Objetos y clases en C# Las clases en C# se definen de forma parecida a los registros (struct), sólo que ahora, además de variables (que representan sus detalles internos, y que llamaremos sus "atributos"), también incluirán funciones (las acciones que puede realizar ese objeto, que llamaremos sus "métodos"). Atributos y métodos formarán parte de "un todo", en vez de estar separados en distintas partes del programa. Esto es lo que se conoce como "Encapsulación". Así, una clase "Puerta" se podría declarar así: public class Puerta {
int ancho;
// Ancho en centimetros
int alto;
// Alto en centimetros
int color;
// Color en formato RGB
bool abierta;
// Abierta o cerrada
public void Abrir() { abierta = true; }
public void Cerrar() { abierta = false; }
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
Como se puede observar, los objetos de la clase "Puerta" tendrán un ancho, un alto, un color, y un estado (abierta o no abierta), y además se podrán abrir o cerrar (y además, nos pueden "mostrar su estado", para comprobar que todo funciona correctamente). Para declarar estos objetos que pertenecen a la clase "Puerta", usaremos la palabra "new", igual que hacíamos con los "arrays": ejemplo = new int[4];
Cuando sepamos cuantos datos vamos a guardar (por ejemplo 4), podremos reservar espacio con la orden "new", así: Puerta p = new Puerta(); p.Abrir(); p.MostrarEstado();
Vamos a completar un programa de prueba que use un objeto de esta clase (una "Puerta"), muestre su estado, la abra y vuelva a mostrar su estado: // Ejemplo_06_02a.cs // Primer ejemplo de clases // Introducción a C#, por Nacho Cabanes
using System;
public class Puerta {
int ancho;
// Ancho en centimetros
int alto;
// Alto en centimetros
int color;
// Color en formato RGB
bool abierta;
// Abierta o cerrada
public void Abrir() { abierta = true; }
public void Cerrar() { abierta = false; }
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
public class Ejemplo_06_02a {
public static void Main() { Puerta p = new Puerta();
Console.WriteLine("Valores iniciales..."); p.MostrarEstado();
Console.WriteLine();
Console.WriteLine("Vamos a abrir..."); p.Abrir(); p.MostrarEstado(); }
}
Este fuente ya no contiene una única clase (class), como todos nuestros ejemplos anteriores, sino dos clases distintas:
La clase "Puerta", que es el nuevo objetos con el que vamos a practicar. La clase "Ejemplo_06_02a", que representa a nuestra aplicación.
(Nota: al compilar, puede que obtengas algún "Aviso" -warning- que te dice que has declarado "alto", "ancho" y "color", pero no las estás utilizando; no es importante por ahora, puedes ignorar ese aviso). El resultado de ese programa es el siguiente: Valores iniciales... Ancho: 0 Alto: 0 Color: 0 Abierta: False
Vamos a abrir... Ancho: 0 Alto: 0 Color: 0 Abierta: True
Se puede ver que en C# (pero no en todos los lenguajes), las variables que forman parte de una clase (los "atributos") tienen un valor inicial predefinido: 0 para los números, una cadena vacía para las cadenas de texto, "false" para los datos booleanos. Vemos también que se accede a los métodos y a los datos precediendo el nombre de cada uno por el nombre de la variable y por un punto, como hacíamos con los registros (struct). Aun así, en nuestro caso no podemos hacer directamente "p.abierta = true" desde el programa principal, por dos motivos:
El atributo "abierta" no tiene delante la palabra "public"; por lo que no es público, sino privado, y no será accesible desde otras clases (en nuestro caso, no lo será desde Ejemplo_06_02a). Los puristas de la Programación Orientada a Objetos recomiendan que no se acceda directamente a los atributos, sino que siempre se modifiquen usando métodos auxiliares (por ejemplo, nuestro "Abrir"), y que se lea su valor también usando una función. Esto es lo que se conoce como "ocultación de datos". Supondrá ventajas como que podremos cambiar los detalles internos de nuestra clase sin que afecte a su uso.
Por ejemplo, para conocer y modificar los valores del "ancho" de una puerta, podríamos crear un método LeerAncho, que nos devolviera su valor, y un método CambiarAncho, que lo reemplazase por otro valor. No hay un convenio claro sobre cómo llamar a a estos métodos en español, por lo que es frecuente usar las palabras inglesas "Get" y "Set" para leer y cambiar un valor, respectivamente. Así, crearemos funciones auxiliares GetXXX y SetXXX que permitan acceder al valor de los atributos (en C# existe una forma alternativa de hacerlo, usando "propiedades", que veremos más adelante):
public int GetAncho() { return ancho; }
public void SetAncho(int nuevoValor) { ancho = nuevoValor; }
Así, una nueva versión del programa, que incluya ejemplos de Get y Set, podría ser: // Ejemplo_06_02b.cs // Clases, get y set // Introducción a C#, por Nacho Cabanes
using System;
public class Puerta {
int ancho;
// Ancho en centimetros
int alto;
// Alto en centimetros
int color;
// Color en formato RGB
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
public class Ejemplo_06_02b {
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(); }
}
También puede desconcertar que en "Main" aparezca la palabra "static", mientras que no lo hace en los métodos de la clase "Puerta". Veremos el motivo un poco más adelante, pero de momento perderemos la costumbre de escribir "static" antes de cada función: a partir de ahora, sólo Main será "static". Ejercicios propuestos:
E jerci jercicio cio propues propues to 6.2.1: Crea una clase llamada Persona, en el fichero "persona.cs". Esta clase deberá tener un atributo "nombre", de tipo string. También deberá tener un método "SetNombre", de tipo void y con un parámetro string, que permita cambiar el valor del nombre. Finalmente, también tendrá un método "Saludar", que escribirá en pantalla "Hola, soy " seguido de su nombre. Crea también una clase llamada PruebaPersona. Esta clase deberá contener sólo la función Main, que creará dos objetos de tipo Persona, les asignará un nombre a cada uno y les pedirá que saluden.
E jerci jercicio cio propues propues to 6.2.2: Tras leer la descripción de Space Invaders que vimos en el apartado anterior, crea una clase Juego,que sólo contenga un método Lanzar, void, sin parámetros, que escriba en pantalla "Bienvenido a Console Invaders. Pulse Intro para salir" y se parará hasta que el usuario pulse Intro. Prepara también un Main (en la misma clase), que cree un objeto de la clase juego y lo lance.
E jerci jercicio cio propues propues to 6.2.3: Para guardar información sobre libros, vamos a comenzar por crear una clase "Libro", que contendrá atributos "autor", "titulo", "ubicacion" (todos ellos strings) y métodos Get y Set adecuados para leer su valor y cambiarlo. Prepara también un Main (en la misma
clase), que cree un objeto de la clase Libro, dé valores a sus tres atributos y luego los muestre.
E jerci jercicio cio propues propues to 6.2.4: Crea una clase "Coche", con atributos "marca" (texto), "modelo" (texto), "cilindrada" (número entero), potencia (número real). No hace falta que crees un Main de prueba. Actualizado el: 28-01-2015 14:16
Ejemplos clases abstractas C# Raw
gistfile1.cs
using System System; ; using System.Collections.Generic ; using System.Linq ; using System.Text ; namespace ConsoleApplication6 { public abstract class Producto { protected double precioVenta precioVenta; ; protected double costoFabrica ; protected string nombreProducto ; public Producto (string nombre, double precio, double costo) { nombreProducto nombreProduct o = nombre; costoFabrica = costo; precioVenta = precio; } public abstract string imprimirDatos imprimirDatos(); (); } public class Libro Libro : : Producto { public Libro Libro(string (string titulo, double precio, double costo) :base base(titulo, (titulo, precio,cos precio,costo) to) { }
public override string imprimirDatos imprimirDatos() () { return "Libro: " + " + nombreProducto + ", Precio: " + precioVenta; } } public class DVD DVD : : Producto { public DVD DVD(string (string titulo, double precio, double costo) : base base(titulo, (titulo, precio, costo) { } public override string imprimirDatos imprimirDatos() () { return "DVD: " + " + nombreProducto + " Precio: " + " + precioVenta; } } class Programu { static void Main Main( (string string[] [] args) { Libro miLibro miLibro = = new Libro Libro( ("Biblioteca del programador" , 54.95 54.95, , 39.95); 39.95 ); DVD miDVD miDVD = = new DVD DVD( ("Curso multimedia de Java" , 29.95 29.95, , 19.95 19.95); ); Console.WriteLine( "Los datos de mis productos productos." ." ); Console.WriteLine(miLibr Console.Write Line(miLibro.imprimir o.imprimirDatos()); Datos()); Console.WriteLine(miDVD. Console.Write Line(miDVD.imprimirDa imprimirDatos()); tos()); Console.WriteLine( "presione para terminar." ); Console.ReadLine(); } } }
Ejemplo Practico de las Clases Abstractas
.
[con C#] Fecha: 27/Oct/2004 (26/Oct/2004) Actualizado: 31/Oct/2006 Autor: SergioTarrillo - Email Blog: sergiotarrillo blog
Quién no llevo P.O.O, ya sea en Java, C++, o ahora en lo que es Net. Todo siempre empezaba bonito crear constructores, hacer herencia, pero cuando llegamos a Clases Abstractas , ahí empiezan los problemas, que son, cual es su diferencia con Interfaces como se relacionan con Polimorfismo, trataremos de definir y explicar todo estos pequeños problemas, auque no es objetivo conocer a fondo a las clases abstractas, solo darle un marco de referencia y ver su aplicación en un ejemplo con C#. Definiciones: 1. Son clases de las que no es posible crear instancias; frecuentemente, están
implementadas sólo parcialmente o no están implementadas. (definición en MSDN library). 2. Una clase abstracta es aquella que forzosamente se ha de derivar si se desea que
se puedan crear objetos de la misma o acceder a sus mi embros estáticos. (con esto suficiente, por ahora). Diferencia con una interface:
Pareciera que son lo mismo, las clases abstractas no se implementa y las interfaces tampoco. Pero las interfaces son mas un conjunto de comportamientos definidos, que esperan ser implementados por el programador. Las clases abstractas, en primer lugar deben ser heredadas para ser implementadas en su totalidad o parcialmente, las clases abstractas se usan mas para una relación de " es un ", como en l a siguiente figura:
Polimorfismo en Clases Abstractas:
Recordar que polimorfismo es la capacidad de un objeto de comportarse de diferentes formas, dependiendo de que clase haya sido instanciada. Si declaramos una clase abstracta, si bien esta no puede ser instaciada si puede ser declarada y l uego ser instanciada por todas las clases que son heredas esto se vera mas adelante en el ejemplo. (en la clase del formulario windows)
cFigura.cs using System; using System.Windows.Forms;
namespace ClasesAbstractas {
abstract class FiguraGeometrica {
public abstract double Area(); }
class Circulo: FiguraGeometrica
{
private int radio;
// A read-write instance property: public int Radio get
{
{ return radio;
} set
{ radio = value;
} }
public Circulo(int r) {
Radio = r; }
public override double Area()
{
return (double)(Radio*Radio*3.14); }
}
//calse tirangulo class Triangulo: FiguraGeometrica {
//propiedades private int ladA; private int ladB; private int ladC;
//propiedades public int LadoA { get { return ladA; } set
{ ladA = value;
} } public int LadoB get
{
{ return ladB;
} set
{ ladB = value;
} }
public int LadoC { get { return ladC; } set { ladC = value; } }
public Triangulo (int a, int b, int c) { LadoA = a; LadoB = b; LadoC = c; }
public override double Area() { double num, mPer;
mPer = (double)(LadoA+LadoB+LadoC)/2;
num = mPer*(mPer-LadoA)*(mPer-LadoB)*(mPer-LadoC);
if (num <= 0 ) { MessageBox.Show("posiblemente el triangulo no exista, intentelo nuevamente"); return 0; } else return Math.Pow(num,0.5);
}
}
class Cuadrado: FiguraGeometrica { //atributos private int lado;
public int Lado { get { return lado; } set
{ lado = value;
} }
public Cuadrado(int l)
{
Lado = l; }
public override double Area()
{
return Lado*Lado; }
} }
Form1.Cs[CmdgetArea_Click]
private void cmdgetAreaCir_Click(object sender, System.EventArgs e) { //area del circulo if (txtRadio.Text != "") { figura = new Circulo(Int32.Parse(txtRadio.Text));
MessageBox.Show("el area del circulo es: " + figura.Area().ToString()); }
//area del triangulo if (txtCuadLad.Text != "") { figura = new Cuadrado(Int32.Parse(txtCuadLad.Text));
MessageBox.Show("el area del cuadrado es: " + figura.Area().ToString()); }
//area del triangulo if (txtTrLA.Text != "" && txtTrLC.Text != "" && txtTrLC.Text != "") { figura = new Triangulo(Int32.Parse(txtTrLA.Text),Int32.Parse(txtTrLB. Triangulo(Int32.Parse(txtTr LA.Text),Int32.Parse(txtTrLB.Text),Int32.Parse(txtTr Text),Int32.Parse(txtTr LC.Text));
MessageBox.Show("el area del triangulo es: " + figura.Area().ToString()); }
}
Ejemplos prácticos de Asociación, Agregación, Composición Composició n y Dependencia con C# .Net Motivación En la actualidad (Mayo 2013) existe mucho material en Internet que habla sobre asociación, composición, composición, agregación y dependencia pero en la mayoría no se pone énfasis en la implementación de los conceptos sino en el análisis conceptual. La realidad es que la forma de implementar cada tipo de relación es diferente (aunque parezcan mínimas las diferencias) pero es muy importante para un programador conocerlas a la hora de leer un diagrama de clases. Es importante también aclarar que un diagrama de clases realizado por un analista funcional no es un modelo que se debe implementar así directamente, sino que debe
ser analizado y comprendido por el programador para producir el verdadero diagrama de clases a implementar. Eso es así debido a que durante el análisis y relevamiento rel evamiento se piensa en "describir" y no en solucionar. Así, el diagrama del analista funcional explica el domino del problema, mientras que el diagrama que realiza el programador explica el dominio de la solución. En este último pueden surgir clases que originalmente no estaban pero son necesarias para realizar una una buena implementación (cuestiones de arquitectura, arquitectura, patrones, etc.).
Aplicación Aplicació n práctica y conceptual Es necesario acostumbrarse al término implementación, el cual se refiere al código de programación concreto de algo. Por ejemplo, si dicen "esta clase es la implementación de aquella " están diciendo "este es el código fuente específico que aplica lo que dice aquella clase abstracta (o interfaz) ". Por tal motivo, en adelante, me referiré directamente al término implementación. Tanto la asociación, agregación, composición y dependencia son formas de representar las relaciones que existen entre clases. Por ejemplo el siguiente diagrama:
La clase Persona tiene una relación de composición con la clase Domicilio. Conceptualmente esto significa que los domicilios son una parte inseparable de la persona, por lo que si no existiera una persona entonces el domicilio de la misma debería desaparecer. Si analizamos más en profundidad encontramos también que, si hubiera que persistir esta relación en una base datos tendríamos una tabla Domicilios cuyo ID sería IdPersona, y una tabla Personas con el mismo ID. El hecho de que la tabla Domicilios no tenga su propio ID sino el de la otra tabla significa que cada registro de la tabla no tiene el peso propio suficiente, que depende 100% de la existencia del mismo ID en la tabla de Personas.
Si se llegase a borrar un registro de la tabla Personas habría que borrar su correspondiente registro de la tabla Domicilios para mantener la integridad de la información. Por esta razón también se dice que la relación de composición es una relación fuerte fuerte,, ya que una instancia instancia arrastra a la otra en caso de eliminación (tanto (tanto de objetos en memoria como de registros en base de datos). Ahora, es válido preguntarse preguntarse ¿por que razón si es algo inseparable inseparable de la persona no lo lo pongo como un atributo más de la clase persona, por ejemplo de tipo string y no me complico tanto? Efectivamente la clase Domicilio es un atributo de la clase Persona, y justamente la línea que las conecta es lo que indica la presencia del atributo. Domicilio existe como clase aparte porque en realidad no es un simple string sino un conjunto de atributos, por ejemplo: calle, localidad, numeración, piso, departamento, etc. Todos esos atributos forman parte de una entidad, el Domicilio, y no sería correcto dejarlos sueltos dentro de la clase Persona. Por eso también se persisten en tablas separadas si fuera necesario. La clase Persona tiene una relación de Agregación de Agregación con con Categoría. Conceptualmente esto significa que las categorías existen independientemente de la persona que la tenga asignada. En el modelo conceptual esto se corresponde con un enunciado como "una persona puede tener una categoría pero una categoría puede estar presente en muchas personas". En un modelo de persistencia relacional tendríamos por un lado la t abla Categorías con su IdCategoría y la tabla Persona con un IdCategoría que señale la relación entre ambas tablas. A diferencia de la la composición, en la agregación agregación la clave primaria primaria de la tabla Categorías es independiente de la clave primaria de la persona, lo cual significa que se puede eliminar un registro de Personas sin que ello afecte la int egridad de la tabla Categorías. Ambos tipos de relación muestran que la forma del objeto (persona (persona en este caso) está está formado por partes externas. La clase Persona tiene una relación de Dependencia Dependencia con con Postulación. Conceptualmente esto significa que la Postulación es un objeto que la Persona utiliza para algún fin, dentro de alguna operación que ella realice (por ejemplo Postularse a un cargo). Pero una Persona no tiene en su interior una Postulación, sino que solo lo utiliza para realizar ciertas operaciones. Esto es lo más importante y diferenciador respecto de las otras dos relaciones; aquí se pone énfasis en el uso de clases dentro de operaciones, es decir, para que una Persona pueda enviar una postulación depende depende la la clase Postulación , quien es capaz realmente de realizar esa operación. Al no tratarse de una una relación que vincula la forma de los objetos, objetos, no existe una forma de persistir esta relación. La clase Persona tiene una relación de Asociación de Asociación con con Sucursal.
Conceptualmente la asociación en un diagrama de clases implica transitividad y bidirección de clases. clases. Por ejemplo una persona tiene como atributo atributo interno a una Sucursal, pero (y aquí está la diferencia) una Sucursal también tiene un atributo de tipo Persona; la cardinalidad de la asociación indicará si Sucursal tiene una o muchas instancias de Persona, con lo cual en realidad el atributo de Sucursal podría ser una Lista o Vector de Personas. Otra característica fundamental es que la vida de las instancias de ambas clases no dependen una de la otra. En un modelo de persistencia relacional podrían suceder dos cosas: si se trata de una cardinalidad de 1 a 1 tendríamos la tabla Personas con su IdPersona más un IDSucusal y la tabla Sucursales Sucursales con su IdSucursal IdSucursal más un IdPersona. Cualquier otra cardinalidad requerirá la tabla Personas y Sucursales con sus Id individuales más una tabla que unifique ambas entidades (tabla de relación) con los campos IdPersona e IdSucursal, la cual permite la navegación en dos direcciones sin invadir a ninguna de las tablas reales. El caso especial se presenta cuando en una asociación es necesario reflejar atributos de información. Por ejemplo, es necesario registrar la fecha de inicio y la fecha de fin de l a vinculación entre empleados y sucursales. Desde el punto de vista de la persistencia no es una complicación ya que la tabla intermedia que vincula a Personas y Sucursales tendrá más campos de información. Pero desde el punto de vistas de entidades hay un cambio más importante: es necesario crear una nueva entidad. Si un vínculo necesita guardar información deja de ser un vínculo y pasa a ser una entidad nueva, nu eva, con derecho a tener su propio nombre (no simplemente la unión de los nombres Persona y Sucursal) porque en el paradigma orientado a objetos todo lo que tenga atributos (características) debe ser una entidad. Sin embargo en el modelo de persistencia la tabla intermedia int ermedia sí suele tener por nombre simplemente la unión de las dos tablas.
Lo que tiene de particular esta entidad es que solo tiene sentido si existen las dos partes, con lo cual en el modelo de persistencia no debe tener clave primaria a
menos que esto no sea cierto y la información del vínculo deba persistir más allá de la menos que existencia de las partes que participaron (si así lo dice el negocio...). En este supuesto sí correspondería agregarle una clave primaria a la tabla intermedia. La implementación de esta entidad intermedia puede resolverse con una clase "TiempoEnSucursal" "TiempoEnSucursa l" (disculpen por el nombre, importa ver que tiene nombre propio), la cual no tendrá un identificador propio, pero tendrá una propiedad de tipo Sucursal y otra de tipo Persona (además de la fecha de inicio y fecha de fin propias de la clase). Por último, estas propiedades de Sucursal y Persona deberían provenir desde afuera de la clase PasoPorSucursal, es decir, por medio de algún constructor o en el "set" de las propiedades.
Para finalizar les dejo la implementación de las clases donde se puede ver en detalle como se aplican los tres tipos de relaciones.
Espero les sea de utilidad este artículo y cualquier inquietud/observación me avisen. Aquí les dejo todo el fuente más la base de datos. https://skydrive.live.com/redir?resid=4285FB631C82DC8C!572 https://skydrive.live.com/redir?resid=428 5FB631C82DC8C!572&authkey=!AM9HFlz &authkey=!AM9HFlz _uXOOTUE Hasta la próxima entrega. Diego Camacho [email protected]
Reacciones: Enviar por correo electrónicoEscribe un blo gCompartir con TwitterCompartir con FacebookCompartir Faceboo kCompartir en Pinterest Etiquetas: Agregacion Etiquetas: Agregacion,, Asociacion Asociacion,, Composicion Composicion,, Dependencia Dependencia,, OOP OOP,, Programación Orientada a Objetos
16 comentarios: Anónimo dijo... dijo... Amigo muy bueno bueno tu articulo. Estoy comenzando comenzando a aprender aprender C# y veía unos videotutoriales donde donde la persona que que explicaba esto no fue claro. Solo una pregunta, Domicilio, Categoría son clases y están declaradas en otra parte... correcto? Si esa clase domicilio contuviera variables, métodos, los puedo accesar desde estas otras clases sin problemas, correcto? 2 de junio de 2013, 8:15
DiegoFox dijo... Hola. Mis disculpas por no responder más prontamente pero nunca me llegó el correo de comentario (o entró como spam, lo probaré...) Si entiendo bien la pregunta, la respuesta es sí: el hecho de que los miembros de Domicilio sean accesibles desde algún lugar lo define el ámbito de alcance que selecciones (private, protected, internal, public). Lo único que siempre se recomienda es no cambiar el private para las variables internas de una clase (campos) porque sino violarías uno de los principios de la
programación orientada a objetos (encapsulamiento (encapsulamiento). ). Para ello deberías utilizar una propiedad (publica por ejemplo) que trabaje con ese campo y comparta su valor. Saludos cordiales! 21 de junio de 2013, 22:46
becavas dijo... Amigo sería valido reemplazar esta propiedad : "Public int PersonaId{get;set; PersonaId{get;set;}" }" por esta propiedad en la clase Domicilio: "Public Persona persona{get persona{get;set;}" ;set;}" que dices? 2 de mayo de 2014, 13:35
Anónimo dijo... dijo... Un domicilio puede existir sin que exista ninguna persona dentro de ella... 10 de julio de 2014, 14:07
Laura_Mejia_A. dijo... "Anónimo Anónimo dijo... Un domicilio puede existir sin que exista ninguna persona dentro de ella... 10 de julio de 2014, 14:07" Sin embargo dentro del contexto, no tiene sentido mantener un domicilio si ya no existe el usuario, ya entiendes? Por ejemplo ahí explican bien, la categoría en cambio si debe existir porque otros deben hacer uso de ellas. 27 de febrero de 2015, 18:28
Anónimo dijo... dijo... Muy buen artículo. Gracias. 5 de mayo de 2015, 7:41
matias p dijo... Es excelente tu artículo, no abunda buena información al respecto...seria muy bueno que publiques publiques mas artículos sobre patrones patrones de diseño con la misma claridad claridad que aquí...saludos! 11 de mayo de 2015, 15:42
Anónimo dijo... dijo... becavas dijo... Amigo sería valido reemplazar esta propiedad : "Public int PersonaId{get;set; PersonaId{get;set;}" }" por esta propiedad en la clase Domicilio: "Public Persona persona{get persona{get;set;}" ;set;}" que dices? Creo lo mismo que el usuario...estaría en lo cierto es asi??? 20 de mayo de 2015, 11:51
Leonardo Jose Giaquinta Ruiz dijo... Muy bueno el artículo! Esperemos que hagas otros! 31 de agosto de 2015, 19:54
Felipe Jaramillo Gomez dijo...
Excelente artículo, es claro, conciso y simple. Muchas gracias. 20 de febrero de 2016, 11:53
nenriquez dijo... Felicidades , tu articulo me resumio las clases del profe de la u, haber si te animas un video sobre los otros diagramas de uml. 28 de marzo de 2016, 14:19
Melisa Gomez Muñoz dijo... La verdad mis felicitaciones por este articulo!!!, te pido por favor si es posible obtener las propiedades de los objetos que participan en la asociacion o composicion con reflection, algun metodo que pueda resolver tal situacion. llevo tiempo intentando resolverlo y no pude. Desde ya muchas gracias!!!! 14 de julio de 2016, 21:01
Melisa Gomez Muñoz dijo... hola, me gustaria saber como obtener las propiedades de un objeto con reflection que tiene otro objeto como atributo o una lista de objetos de otra clase como atributo, por ejemplo: clase persona tiene como atributo a la clase domicilio o podria ser una lista del tipo domicilio como atributo. Esto es posible mediante reflection??? te agradeceria tu respuesta ya que lllevo tiempo intentando resolver esta situacion y nada... 14 de julio de 2016, 22:04
Victor Aguilera Aguilera dijo... Excelente!! Muchas felicitaciones. No había visto que alguien explicara los conceptos de asociación, agregación, composición y dependencia incluyendo la perspectiva de la base de datos. Gran aporte aún en esta fecha. 12 de junio de 2017, 3:48
Anónimo dijo... dijo... Excelente aporte, luego de tantas bùsquedas intensivas en cierto buscador famosìsimo para terminar de hacer mi bendito trabajo pràctico con diagramas UML, debo decir que esta es el primer apunte que encuentro tan bien explicado.Muchìsimas gracias 20 de septiembre de 2017, 0:26
Héctor dijo... Y que sucede cuando un domicilio es compartido por varias personas?, personas?, ya que en un mismo domicilio pueden vivir varias personas. Si elimina alguna de esas personas (quedando activas o vigentes las demás) se tendría que eliminar el domicilio? 19 de octubre de 2017, 12:41 Publicar un comentario Entrada más recienteEntrada antiguaPágina antigu aPágina principal Suscribirse a: Enviar comentarios (Atom)