Está en la página 1de 26

Material exclusivo para uso interno en la Escuela Técnica Nro 12

Programación Orientada a Objetos


Escuela Técnica Nro. 12 – 5to 8va

1. Programación basada en objetos


1.1 Objetos, estado y comportamiento, propiedades y métodos
Un objeto es aquella entidad capaz de almacenar estado y responder a comportamiento. Para
establecer una comparación con el paradigma anterior, es decir, la programación estructurada; se
puede decir que un objeto se asemeja a una variable, pero no sólo sirve para almacenar valores, sino
que también contiene las operaciones que se pueden aplicar a esos valores. Esos objetos tienen
estado, comportamiento e identidad:

➔ El estado de un objeto es el conjunto de valores internos que un objeto tiene, que representa
la situación en que está. El estado puede ser observable, sí el objeto permite que sea
conocido por otros objetos de la aplicación, u oculto, si no se permite verlo desde otros
objetos.
➔ El comportamiento de un objeto es el conjunto de respuestas que un método exhibe ante
solicitudes de otros objetos. En algunos casos, el comportamiento depende del estado en que
se encuentre dicho objeto.
➔ La identidad de un objeto es lo que lo diferencia de los demás objetos de su clase. Por
ejemplo, el auto con matricula AB1234CD tiene una identidad que lo diferencia de los
demás autos de la misma marca, modelo y color; aún cuando tengan el mismo
comportamiento y estén en el mismo estado. La identidad se le otorga en el momento de la
creación del mismo y se mantiene durante toda la vida. Es independiente del estado y la
localización física.
Para acceder al estado observable de un objeto, se utilizan las propiedades, que se accede
mediante el nombre de la variable seguida de un puto y el nombre de la propiedad.

El comportamiento describe los estímulos y reacciones de un objeto, dicho de otro modo, los
servicios que brinda. Es la manera en que éste reacciona ante mensajes o estímulos recibidos,
básicamente enviando mensajes a otros objetos, respondiendo al que le envía el mensaje o
cambiando de estado. Las distintas formas de respuesta se denominan métodos y corresponden a
procedimientos y funciones. Para llamar a un método de un objeto se coloca el nombre de la
variable seguida de puto y el nombre del método con sus argumentos.

1
Material exclusivo para uso interno en la Escuela Técnica Nro 12

En POO (Programación Orientada a Objetos) un objeto puede satisfacer solamente ciertos


requisitos, definidos por su interfaz, que es el conjunto de los métodos y propiedades aplicables a
ese objeto. Son la propia interfaz y la implementación de la misma quienes definen el
comportamiento y estado observable de un objeto.

Cuando se invoca un método sobre un objeto o se le pide el valor de una propiedad, se dice que le
estamos pasando un mensaje.

Ejemplos:

public class ClaseArregloDesordenado


{
private readonly int Max; // Tamaño del arreglo
public int Top; // Variable para contar la cantidad de celdas ocupadas Propiedades
public int[] Arreglo; // Declaración del arreglo

public bool EstaLleno() // Método para detectar si el arreglo está lleno


{
if (Top == Max)

else Método
return (false);
}
}

Un objeto se genera a partir de una clase. Puedo tener varios objetos cuya identidad sea diferente a
partir de una misma clase (recordar el ejemplo del auto). Aplicado a la clase anterior el objeto
creado se llama “ArregloDesordenado”
class Program
{
static ClaseArregloDesordenado ArregloDesordenado = new ClaseArregloDesordenado(10);
// Declaracion del objeto
Objeto
static ClaseArregloDesordenado ElArreglo = new ClaseArregloDesordenado(10);
static void Main(string[] args)
{
ArregloDesordenado.Top=10; // se modifica el valor de la propiedad Top
ArregloDesordenado.EstaLleno();//Se invoca el método del objeto EstaLleno
(mensaje)

ElArreglo.Top=10;
}
}

La variable Top va a poder recibir el mismo mensaje por ser instancia del mismo tipo
ClaseArregloDesordenado pero como representa objetos distintos (ArregloDesordenado y

2
Material exclusivo para uso interno en la Escuela Técnica Nro 12

ElArreglo), con una identidad distinta, se va a obtener distintos valores y resultados enviando los
mismos mensajes.
Las clases se pueden agrupar de alguna manera, habitualmente conocida como paquetes. Un
paquete es un agrupamiento que se hace primordialmente para ordenar las clases en un sistema
mediano o grande, y para resolver conflictos de nombres. Por eso, algunos lenguajes -como C++ y
C#- los llaman espacios de nombres. Por ejemplo el paquete System, contiene a la clase Console.

1.2 Constructores y Destructores


El Constructor es el primer método que se debe invocar para un objeto, y realiza una tarea de
inicialización necesaria. El Constructor debe poseer en C# el mismo nombre que la Clase. En el
ejemplo dado podría ser:

public class ClaseArregloDesordenado


{
private readonly int Max; // Tamaño del arreglo
public int Top; // Variable para contar la cantidad de celdas ocupadas
public int[] Arreglo; // Declaración del arreglo

public ClaseArregloDesordenado(int m) // Constructor


{
Max = m; // Se inicializa el tamaño del arreglo
Top = 0; // Se inicializa el arreglo vacío
Arreglo = new int[Max]; // Creación del arreglo
}

public bool EstaLleno() // Método para detectar si el arreglo está lleno


{
if (Top == Max)
return (true);
else
return (false);
}
}

El concepto de Destructor es un poco menos frecuente. Su uso habitual es la destrucción de un


objeto. Su sintaxis es: ~[nombre del objeto]

1.3 Tipos por valor y por referencia


Los lenguajes con orientación a objetos suelen trabajar, en algunos casos, con tipos por valor, y en
otros con tipos por referencia. Hay algunos lenguajes que trabajan con ambos modelos, como es el
caso de C# y Java. Algunos tipos de datos de C# y Java, como int o char y todos los tipos de C++,

3
Material exclusivo para uso interno en la Escuela Técnica Nro 12

son tipos por valor. Esto significa que las variables de esos tipos son creadas en memoria (en la
pila) en el momento en que el programa pasa por la declaración de las mismas, y destruidas cuando
termina el ámbito en el cual han sido declaradas.

Una variable del tipo por referencia no contiene directamente los datos almacenados, sino la
dirección de memoria (la referencia) del lugar donde están los datos. La declaración de una variable
de un tipo por referencia no alcanza para guardar espacio para el mismo, sino que esto se hace
dinámicamente más tarde mediante una sentencia especial, que en C# y Java se denomina new.
Cualquier variable de un tipo por referencia puede tomar el valor nulo (en Java y C#, la constante
null) lo que significa que no está referenciando nada.

Cuando trabajamos con objetos, lo que suele interesar es la identidad, lo que diferencia a un objeto
particular de otro. Por eso, tiene sentido toda comparación entre objetos, realizada con == y con !=,
que sirve para saber si se trata del mismo objeto, no de si tiene el mismo contenido.

2. Programación y Diseño
2.1 Construcción de clases
Partamos de un ejemplo. Supongamos que tenemos que implementar un sistema bancario muy
simple. Si analizamos qué entidades aparecen en el dominio del problema, una de ellas sería sin
duda el concepto de cuenta.

La POO intenta convertir los objetos (no necesariamente físicos) del dominio del problema, en,
objetos del dominio de la solución. Esto significa que habría objetos de algún tipo como “cuenta”
en nuestra solución. Esto se lleva a cabo implementando una clase que llamaré CuentaBancaria,
que sirva de molde para crear los objetos concretos. Para garantizar que al crear una cuenta esta
tenga un número y un titular, y evitar que se creen cuentas sin número ni titular, es necesario que la
creación de objetos se produzca llamando al constructor. Una primera idea sería:

CuentaBancaria cuenta = new CuentaBancaria(2345, “García”); //número, titular

Es decir, estamos diciendo que cuando creemos un objeto CuentaBancaria, le vamos a pasar como
valores iniciales el numero de cuenta y el nombre del titular.

Otra cosa que debemos poder hacer es depositar dinero. Pensemos en un método Depositar().

Cuenta.Depositar(2000); //depósito de $2000

4
Material exclusivo para uso interno en la Escuela Técnica Nro 12

También se debería poder extraer dinero. Aquí existe un punto crítico en nuestra implementación.
Podría no haber saldo suficiente en la cuenta. Por lo tanto, vamos a suponer que el método Extraer
me indique con un resultado booleano si se pudo o no hacer la extracción.

Bool éxito = cuenta.Extraer(700);

if(exito) Console.WriteLine(“Fondos Insuficientes”);

Por último, en toda cuenta bancaria es importante conocer el saldo, es decir, el dinero que quedó en
mi cuenta después de realizar las operaciones. La línea sería,

Console.WriteLine(cuenta.Saldo);

Implementación

Escribamos el código. A la clase Program agregarle una clase, que como vimos en el ejemplo se
llama CuentaBancaria.

Lo primero que debemos preguntarnos es qué datos internos va a necesitar almacenar un objeto
CuentaBancaria. De lo planteado anteriormente, resulta que el número de cuenta, el nombre del
titular y por supuesto, el saldo. Por lo tanto, los atributos de la clase se definen de la siguiente
manera:

private int numero;

private string titular;

private double saldo;

tambien dijimos ue existirá una propiedad Saldo,

public double Saldo{ //para consultar el saldo, nótese la diferencia entre minúscula atributo y
mayúscula propiedad

get{

return saldo;

//para darle valor al saldo

set{

5
Material exclusivo para uso interno en la Escuela Técnica Nro 12

saldo=value;

Esta propiedad Saldo permite conocer el saldo, pero no en forma arbitraria. El saldo sólo podrá
alterarse por los depósitos y las extracciones. Una mejor definición de la propiedad sería entonces
hacerla de consulta solamente,

public double Saldo{

get{

return saldo;

Ahora escribimos los métodos Depositar y Extraer,

public void Depositar(double monto){

saldo+=monto;

public bool Extraer(double monto){

if(monto>saldo)

return false;

else{

saldo+=monto;

return true;

Recuérdese que todo este código pertenece a la clase CuentaBancaria.

6
Material exclusivo para uso interno en la Escuela Técnica Nro 12

Anteriormente hablamos de la importancia del constructor, recuerden que dijimos que no podía
existir una cuenta bancaria sin número ni titular, es decir no puede existir un objeto que no contenga
valores en dichas propiedades.

Public CuentaBancaria(int n, string t){ //constructor. Posee el mismo nombre que la clase

numero=n;

titular=t;

saldo=0;

Una vez que tenemos escrito el código de la clase pasamos a la clase Program y generamos el
objeto asignándole valores a sus propiedades.

Public static void Main(){

CuentaBancaria cuenta = new CuentaBancaria(2345,”Garcia”);

cuenta.Depositar(2000);

bool éxito = cuenta.Extraer(700);

if (!exito) Console.WriteLine(“Fondos Insuficientes”);

Console.WriteLine(cuenta.saldo);

¿Se comprendió el código? Probarlo.

Ejercicio

¿Se anima a modificar el programa para que incluya un Menu que me pida los datos de número de
cuenta, nombre y me permita depositar, extraer, ver el saldo y salir?

2.2 Calificadores de accesibilidad


Los atributos, propiedades y métodos privados sólo se pueden usar desde dentro de la clase en la
que están definidos, y no desde ninguna otra. Sólo podemos referirnos a un método, atributo o
propiedad privado desde el código propio de la clase, el que se encuentra entre las llaves que

7
Material exclusivo para uso interno en la Escuela Técnica Nro 12

delimitan su definición. Cualquier intento de acceder desde fuera de la misma, provocará un error
de compilación, ya que fuera de la clase, el método, atributo o propiedad en cuestión, no existe.

Los atributos, propiedades y métodos públicos se pueden usar desde cualquier lado, dentro o fuera
de la clase en cuestión.

En C# podemos usar el calificador de visibilidad internal, y en ese caso le estamos dando


visibilidad a todo el ensamblaje.

Las clases también tienen calificadores de accesibilidad. En C# si a una clase no se le coloca un


calificador de accesibilidad se asume que es internal.

2.3 Implementación de métodos y propiedades de clase


Hay propiedades y métodos que se utilizan, no para cada objeto, sino para toda una clase. En C#
esto se logra introduciendo la palabra static en la declaración del método o la propiedad. Como los
métodos y propiedades de la clase sólo actúan sobre la clase, y no sobre una instancia determinada,
sólo pueden acceder a métodos, propiedades y atributos de clase. Tampoco tienen acceso al objeto
this. Por ejemplo, si tenemos una aplicación que tiene muchas ventanas, y estas son objetos de una
clase y deseamos cambiar el color de fondo de todas las ventanas, hasta ahora habrá que definir en
cada objeto el cambio de color; pero si se realiza sobre la clase los objetos cambiaran
automáticamente su color, para ello se define en la clase de la siguiente manera.

Private static int colorFondo;

En C# se pueden definir también constructores de clase. Estos constructores se invocan una vez
para cada programa, antes de crear cualquier instancia de esa clase. A veces se los utiliza para
inicializar atributos de clase que no se pueden asignar directamente en el código fuente. Los
constructores de clase se declaran con la palabra static y sin poner un calificador de acceso, ya que
no se invocan directamente en el código de ningún programa. Por supuesto, tampoco tienen
parámetros. Un uso, quizá un poco avanzado, de los constructores de clase, es el siguiente:
supongamos que tenemos un atributo de clase que se debe inicializar utilizando un valor guardado
en un archivo externo. ¿dónde pondríamos el código que lee ese archivo? ¡Adivinó...en un
constructor de clase!

8
Material exclusivo para uso interno en la Escuela Técnica Nro 12

2.4 Atributos con valor constante


A veces ocurre que en una clase un determinado atributo debe tener siempre el mismo valor. Por
ejemplo, un identificador de cliente o de cuenta que no se modifica mientras exista el cliente. En ese
caso se trata de un atributo constante que es distinto para cada instancia.

En C#, un atributo con valor constante se define anteponiéndole la palabra readonly en su


declaración, pero sólo si es de n tipo por valor. Estas constantes se pueden inicializar en el
constructor con valores obtenidos en tiempo de ejecución, pero una vez inicializadas no se pueden
modificar.

A los atributos por referencia se les puede colocar el modificador readonly pero eso sólo afectaría a
la referencia. En este caso, lo que no se va a poder hacer con el atributo es un nuevo new, que
cambiaría la referencia del atributo.

Readonly int limiteextracción; // se inicializa en el constructores

existe el modificador const para declarar constantes. El problema es que sólo se puede usar con
tipos por valor, y además debe colocarse el valor de la constante en el código junto con la
declaración del atributo. Por lo tanto no es el constructor donde se la asigna un valor, y tampoco
puede definirse en tiempo de ejecución.

2.4 Principios elementales de diseño de clases


El primer principio es que cada clase debe tener un propósito simple y claro. Es el principio que se
conoce con la máxima “una clase por abstracción y una abstracción por clase”.

Esto significa que una clase se debe referir a no más de una entidad del problema que se está
resolviendo, además de que debe poder explicarse qué representa dicha clase de una manera simple,
y en lo posible contener -la oración de la descripción- un sólo sujeto.

Por ejemplo, podemos tener una clase Factura que contenga datos de un cliente y una serie de
artículos, pero deberíamos trabajar con 3 clases: Factura, Artículo y Cliente.

Un rasgo característico de un mal diseño de clases es la aparición de clases sin estado (no tienen
atributos ni propiedades), o sin comportamiento (sin métodos, además de los get y set de
propiedades). Se las suele llamar clases degeneradas o anémicas. La clase es una entidad que provee
un conjunto de servicios y no se supone que una clase hace algo.

9
Material exclusivo para uso interno en la Escuela Técnica Nro 12

Si la solución del problema presenta restricciones, estas se deben expresar en los atributos y
debemos garantizar que no haya ningún método o propiedad que pueda alterar el cumplimiento de
la misma, para garantizar la simplicidad de la clase, es una buena práctica el separar el
cumplimiento de las restricciones en una clase aparte.

2.5 Diseño de métodos


La primera receta a tener en cuenta es que cada método debe hacer una sola cosa simple. Esto es lo
que se conoce como alta cohesión y que se suele reforzar diciendo que cada método deberá poder
ser descripto por una oración simple sobre su propósito. Incluso las pruebas booleanas conviene
separarlas en métodos aparte cando contienen conectivos lógicos, de modo tal que las condiciones
de ciclos y decisiones sean lo más simple posible. Ejemplos

private boolean bisiesto(){

if ((anio%4 ==0) && ((anio%400==0) || ((anio%100 !=0)))

return true;

else return false;

public int diasMes(){

boolean bisiesto=bisieso();

if ((mes==2) && !bisiesto) return 28;

if ((mes==4) || (mes==6) || (mes==9) ||(mes==11))

return 30;

else return 31;

Quedaría mejor si simplificamos las complejas condiciones lógicas y convertir la cantidad de días
por mes en una tabla:

private boolean anioMultiploDe(int n){

10
Material exclusivo para uso interno en la Escuela Técnica Nro 12

return (anio%n==0);

private boolean bisiesto(){

if(anioMultiploDe(400))

return true;

else if (anioMultiploDe(4) && !anioMultiploDe(100)

return true;

else return false;

public int diasMes(){

int diasMes[]={0,31,28,31,30,31,30,31,31,30,31,30,31};

int dias=diasMes[mes];

if((mes==28) && bisiesto())

dias=29;

return dias;

Ejercicios

1) Explique en una oración simple lo que hace cada método de la clase.

2)¿Por qué int diasMes[]={0,31,28,31,30,31,30,31,31,30,31,30,31}; comienza con “0”?

3) Este ejemplo es un fragmento. Escriba la aplicación completa.

Otra cuestión del diseño de métodos es evitar el código duplicado. Si parte del código de un método
es similar a una parte del de otro método, deberíamos hacer nuestro mayor esfuerzo para lograr
construir un método -privado- que sea llamado desde ambos, con los parámetros que sean
necesarios.

11
Material exclusivo para uso interno en la Escuela Técnica Nro 12

Evitar que la llamada desde un método publico implique la necesidad de llamar a otro método
también publico. De alguna manera cuando implementamos cosas así estamos violando el
ocultamiento ya que es obligatorio que conozcamos aspectos internos de los métodos, y sus
interrelaciones. La única excepción a esta regla son los constructores, que deben ser llamados antes
de cualquier otro método para cada instancia.

2.6 ¿Métodos o propiedades?


Los métodos se utilizan para definir y obtener el comportamiento de los objetos. Las propiedades
deben utilizarse para definir y obtener el estado observable de los mismos. Pero hay ocasiones que
quedan dudas. Como regla general puede considerarse que el valor de una propiedad deberá ser
simple de escribir en código, normalmente devolviendo el valor de un atributo o un cálculo que
involucre alguno de ellos, sin necesidad de solicitar servicios a otras clases. Si no es así, sospeche
de estar en presencia de un método.

2.7 Conclusiones
El encapsulamiento o la conjunción de abstracción más ocultamiento de la implementación, es uno
de los pilares de la POO. Al poner juntos el comportamiento y los atributos, evitamos errores. Esto
permite aumentar la complejidad de los sistemas sin abrumar al cliente de la clase. Vimos que el
concepto principal de la POO es el de clase, que nos sirve tanto como tipo definido por el
programador como conjunto de objetos. Si bien se utilizan objetos, estos deben ser instancias de
clases definidas previamente.

12
Material exclusivo para uso interno en la Escuela Técnica Nro 12

3. Delegación
Veamos a través de un ejemplo. Supongamos que se quiere informatizar un club de inmobiliarias
que tiene inmuebles y clientes., de forma tal que los clientes puedan mostrar interés, reservar y
comprar un inmueble independientemente de la inmobiliaria que lo esté ofreciendo. Si un inmueble
cambia su precio se debe avisar a todos los clientes que mostraron su interés en él. Si un inmueble
se saca del mercado, se deberá avisar a todos los interesados.

El problema a resolver será crear el modelo de clases e implementar una parte del comportamiento
deseado.

3.1 Modelos de clases


El modelo de clases lo haremos utilizando el diagrama de clases de UML. El diagrama de clases es
un modelo estático del sistema a construir o de parte del mismo. En él se muestra clases y
relaciones entre las mismas.

En el diagrama Inmobiliaria e Inmueble son clases, nombre y superficie son atributos, AvisarVenta
y Vender son métodos. Los atributos, métodos y propiedades que están precedidos de un guión
(signo menos, -) son privados, mientras los que siguen a un signo más (+) son públicos. De cada
método, atributo y propiedad se puede indicar su tipo, como el caso del atributo email cuyo tipo es
string.

Las líneas que vinculan clases se llaman asociaciones, y en términos de programación significan
que una clase tiene un atributo cuyo tipo es la otra clase. Las flechasen esas líneas indican el sentido
de navegación de la relación, es decir, cuál es la clase que contiene el atributo (origen de la flecha) y
cuál la del tipo atributo (extremo de la flecha). Las asociaciones pueden tener cardinalidad, lo cual
indica de cuántos atributos estamos hablando. Por ejemplo, en el diagrama, la asociación entre
Inmobiliaria e Inmueble tiene un 1 y un *, que indican que por cada inmobiliaria hay varios
inmuebles.

13
Material exclusivo para uso interno en la Escuela Técnica Nro 12

Inmobiliaria
- nombre: string
+ AgregarInmueble (p: Inmueble)
+ QuitarInmueble (p: Inmueble)
+ImprimirDatos()
1
*

Inmueble
- domicilio: string
- superficie: double
- cantAmbientes: int
- precio: int
- reservado: bool
- vendido: bool
+ AnotarInteresado (c: Cliente)
+ EliminarInteresado (c: Cliente)
+ Reservar()
+ Vender()
+ ImprimirDatos()
1

Cliente
- nombre: string
- telefono: string
- email: string
+ AvisarCambioPrecio()
+ AvisarVenta (p: Inmueble)
+ AvisarReserva (p: Inmueble)

3.2 Diagrama de Secuencia


Este diagrama es una herramienta ideal para ver cómo interactúa un conjunto de objetos en un
escenario determinado. Esto nos servirá para obervar que ocurre dentro de cada llamada del
programa de prueba, lo que nos ayudará a ir pensando en la implementación de las clases (código de
los métodos).

14
Material exclusivo para uso interno en la Escuela Técnica Nro 12

3.3 Un programa de prueba


El programa que proponemos a modo de prueba y diseño de las clases que lego vamos a programar
es:

public class Prueba Inmobiliarias{

public static void Main(){

15
Material exclusivo para uso interno en la Escuela Técnica Nro 12

//creación de objetos de prueba

Cliente ana = new Cliente(“Ana”,”02944523698”, “ana@suempresa.com.ar”);

Cliente joaquin = new Cliente(“Joaquin”,”02234797152”,”joaquin@mdp.com.ar”);

Cliente clara = new Cliente(“Clara”,”0114562316”,”clara@fi.uba.ar”);

Inmueble membrllar = new Inmueble(“Membrillar 25”,85.3,4,82000);

Inmueble boyaca = new Inmueble(“Boyacá” 1244”,144.3,5,124300);

Inmueble artigas = new Inmueble(“Artigas 1366”,95.2,3,94500);

Inmueble neuquen = new Inmueble(“Neuquén 3455”,129.4,5, 129500);

Inmobiliaria sucasa = new Inmobiliaria(“Su Casa”);

Inmobiliaria flores = new Inmobiliaria(“Flores”);

//Impresión básicamente

boyaca.ImprimirDatos();

Console.WriteLine();

//carga de inmobiliarias

sucasa.AgregarInmueble(membrillar);

sucasa.AgregarInmueble(neuquen);

flores.AgregarInmobiliaria(boyaca);

flores.AgregarInmueble(artigas);

//carga de interesados

membrillar.AnotarInteresado(ana);

artigas.AnotarInteresado(ana);

boyaca.AnotarInteresado(joaquin);

neuquen.AnotarInteresado(joaquin);

boyaca.AnotarInteresado(clara);

16
Material exclusivo para uso interno en la Escuela Técnica Nro 12

//Imprimiendo inmuebles e interesados

sucasa.ImprimirDatos();

flores.ImprimirDatos();

//movimientos

membrillar.Precio=92500;

membrillar.Reservar();

membrillar.Vender();

neuquen.EliminarInteresado(joaquin);

nequen.ElimiarInteresado(ana);

//Impresion inmueble e interesados

sucasa.ImprimirDatos();

flores.ImprimirDatos();

//fin

Console.ReadLine();

Con este programa como guía, vamos a intentar escribir las clases respectivas

IMPLEMENTACIÓN

public class Inmobiliaria{

private string nombre;

private int cantidadInmuebles;

private const int maximoInmuebles = 100;

private Inmueble[] inmuebles;

public Inmobiliaria(string nombre){

17
Material exclusivo para uso interno en la Escuela Técnica Nro 12

this.nombre=nombre;

this.inmuebles=null;

this.cantidadInmuebles=0;

public string Nombre{

get{

return nombre;

public int CantidadInmuebles{

get{

return cantidadInmuebles;

public void AgregarInmueble(Inmueble x){

if(cantidadInmuebles==maximoInmuebles){

WriteLine(“Se superó el máximo de inmuebles para esta inmobiliaria”);

return;

if(Inmuebles==null)

inmuebles= new Inmueble[maximoInmuebles];

inmuebles[cantidadInmuebles]=x;

cantidadInmuebles++;

18
Material exclusivo para uso interno en la Escuela Técnica Nro 12

public void QuitarInmueble (inmueble x){

if(inmuebles==null)

return;

int pos = Array.IndexOf(inmuebles, x);

if(pos>-1){

for (int i=pos; i<cantidadInmuebles-1,i++){

inmuebles[i]=inmuebles[i+1];

inmuebles[cantidadInmuebles-1]=null;

cantidadInmuebles--;

public void ImprimirDatos(){

Console.WriteLine(“Inmobiliaria: ” + this.Nombre);

if(inmuebles!=null)

for(int i=0; i<cantidadInmuebles; i++)

inmuebles[i].ImprimirDatos();

Console.WriteLine();

La clase Inmueble queda

public class Inmueble{

private string domicilio;

19
Material exclusivo para uso interno en la Escuela Técnica Nro 12

private double superficie;

private int cantidadAmbientes;

private int precio;

private Cliente[] interesados;

private int cantidadInteresados;

private const int maximointeresados=1000;

private bool reservado;

private bool vendido;

public Inmueble (string domicilio, double superficie, int cantidad Ambientes, int precio)

this.domicilio=domicilio;

this.superficie=superficie;

this.cantidadAmbientes=cantidadAmbientes;

this.precio=precio;

this.interesados=null;

this.reservado=false;

this.vendido=false;

public string domicilio{

get{

return domicilio;

public double Superficie{

20
Material exclusivo para uso interno en la Escuela Técnica Nro 12

get{

return superfice;

public int CantidadAmbientes{

get{

return cantidadAmbientes;

public int Precio{

get{

return precio;

set{

precio=value;

if(interesados != null)

for(int i=0; i<cantidadInteresados; i++)

public void AnotarInteresado (Cliente c){

if (cantidadInteresados == maximointeresados){

Console.WriteLine(“Se superó el máximo de interesados para este inmueble”);

return;

21
Material exclusivo para uso interno en la Escuela Técnica Nro 12

if (interesados == null)

interesados = new Cliente[maximointeresados];

interesados[cantidadinteresados] = c;

cantidadInteresados++;

public bool Reservado{

get{

return reservado;

public void Reservar(){

reservado=true;

if (interesados != null)

for (int i=0; i<cantidadInteresados; i++);

interesados[i].AvisarReserva(this);

public bool Vendido{

get{

return vendido;

public void Vender(){

vendido=true;

if(interesados != null)

22
Material exclusivo para uso interno en la Escuela Técnica Nro 12

for(int i=0; i<cantidadInteresados; i++)

interesados[i].AvisarVenta(this);

public void ImprimirDatos(){

Console.WriteLine(“Domicilio: “ + Domicilio);

Console.WriteLine(“Superficie: “ + Superficie);

Console.WriteLine(“Cantidad de Ambientes: “ + CantidadAmbientes);

Console.WriteLine(“Precio: “ + Precio);

Console.WriteLine(“Reservado: “ + Reservado);

Console.WriteLine(“Vendido: “ + Vendido);

Console.WriteLine(“Cantidad de Interesados: “ + cantidadInteresados);

for (i=0; i<cantidadInteresados; i++)

Console.WriteLine(Interesados[i].Nombre);

y la clase Cliente sería:

public class Cliente{

string nombre;

string teléfono;

string email;

public Cliente (string nombre, string teléfono, string email)

this.nombre=nombre;

23
Material exclusivo para uso interno en la Escuela Técnica Nro 12

this.telefono=telefono;

this.email=email;

public string Nombre{

get{

return nombre;

public string Telefono{

get{

return teléfono;

publis string Email{

get{

return email;

public void CambiarTelefono (string nuevo){

teléfono = nuevo;

public void CantidadEmail(string nuevo){

email = nuevo;

24
Material exclusivo para uso interno en la Escuela Técnica Nro 12

public void AvisarCambioPrecio (Inmueble x, int nuevoPrecio){

string mensaje = “El Inmueble “ + x.Domicilio + “en el que estaba interesado ha cambiado
de precio. Hoy cuesta $” + nuevoPrecio;

enviarMail (mensaje, “con nuevo precio”);

public void AvisarReserva (Inmueble x){

string mensaje = “El Inmueble “ + x.Domicilio + “en el que estaba interesado ha sido
reservado”;

enviarMail (mensaje, “Reservado”);

public void AvisarVenta (Inmueble x){

string mensaje = “El Inmueble “ + x.Domicilio + “en el que estaba interesado ha sido
vendido”;

enviarMail (mensaje, “Vendido”);

public void enviarMail (string mensaje, string evento){

#warning “enviar mail: Implementarlo antes de salir a producción”

Console.WriteLine(“Mail a “ +this.Nombre);

Console.WriteLine(evento);

Console.WriteLWritine(mensaje);

Console.WriteLine();

Un aspecto nuevo de este ejemplo es el uso de la clase Array, que tiene un método de clase IndexOf
para buscar un objeto en un arreglo, devolviendo su posición, o -1 si no se encuentra.

25
Material exclusivo para uso interno en la Escuela Técnica Nro 12

Lo novedoso de este ejemplo es que hemos usado algunas clases como tipo de algunos atributos de
otras clases. Por ejemplo, la clase Cliente es el tipo de los elementos del arreglo interesados,
atributo de la clase Inmueble. Lo mismo ocurre con la propia clase Inmueble, que la utilizamos
para definir el tipo de los elementos de un atributo de la clase Inmobiliaria.

El hecho de tener un atributo dentro de Inmobiliaria cuyo tipo sea Inmueble, nos habilita para
llamar métodos de clase Inmueble desde dentro de métodos de la clase Inmobiliaria, que invoca al
ImprimirDatos de Inmueble, utilizando el arreglo inmuebles.

3.4 Diagramas de UML: Formalización

26

También podría gustarte