You are on page 1of 23

temII.

CLASES Y OBJETOS
Cuando se escribe un programa en un lenguaje orientado a objetos, definimos una plantilla o clase que describe las caractersticas y el comportamiento de un conjunto de objetos similares. Por ejemplo, la clase automvil describe las caractersticas comunes de todos los automviles: sus atributos y su comportamiento. Los atributos o propiedades se refieren a la marca o fabricante, el color, las dimensiones, si tienen dos, tres, cuatro o ms puertas, la potencia, si utiliza como combustible la gasolina o gasoil, etc. El comportamiento se refiere a la posibilidad de desplazarse por una carretera, frenar, acelerar, cambiar de marcha, girar, etc. Luego, tenemos automviles concretos, por ejemplo el automvil propio de una determinada marca, color, potencia, etc., el automvil del vecino de otra marca, de otro color, etc., el automvil de un amigo, etc. Una clase es por tanto una plantilla implementada en software que describe un conjunto de objetos con atributos y comportamiento similares. Una instancia u objeto de una clase es una representacin concreta y especfica de una clase y que reside en la memoria del ordenador. 2.1 Declaracin de clases: atributos, mtodos, encapsulamiento. a. Atributos Los atributos son las caractersticas individuales que diferencian un objeto de otro y determinan su apariencia, estado u otras cualidades. Los atributos se guardan en variables denominadas de instancia, y cada objeto particular puede tener valores distintos para estas variables. Las variables de instancia tambin denominados miembros dato, son declaradas en la clase pero sus valores son fijados y cambiados en el objeto. Los atributos son todas las caractersticas de los objetos que estn en una clase, como son, su forma, tamao, color, etc. Los atributos pueden ser los externos los que se ven a simple vista y los internos que son los que componen al objeto. Hay variables de instancia y hay variables de clase, las cuales se aplican a la clase y a todas sus instancias. Por ejemplo, el nmero de ruedas de un automvil es el mismo cuatro, para todos los automviles. Ejemplo: un avin sus atributos son; tiene alas, es de acero, tiene llantas, etc., pero tambin tiene componentes internos, como los circuitos, los motores, el cableado etc.

b. Mtodos Un mtodo es un conjunto de instrucciones que realizan una determinada tarea y son similares a las funciones de los lenguajes estructurados. Son funciones que pueden ser llamadas dentro de la clase o por otras clases. Es el procesamiento que realiza un objeto. Del mismo modo que hay variables de instancia y de clase, tambin hay mtodos de instancia y de clase. En el primer caso, un objeto llama a un mtodo para realizar una determinada tarea, en el segundo, el mtodo se llama desde la propia clase. Cuando se enva un mensaje a un objeto, se implementa el mtodo. Un mtodo en si es lo que el objeto puede hacer, y este lo ejecuta cuando se le da una orden o se programa para que este lo haga en determinado momento. Ejemplo: una aspiradora: aspira polvo, infla cosas, sopletea objetos, etc.

c. Clase Una clase es un conjunto de objetos que comparten una estructura y comportamiento comunes. Clase representa una abstraccin, la esencia que comparten los objetos. Un objeto es un ejemplo de una clase. Un objeto no es una clase, y una clase no es un objeto. Las clases actan como intermediarias entre una abstraccin y los clientes que pretenden utilizar la abstraccin. De esta forma, la clase muestra:

1. visin externa de comportamiento (interface), que enfatiza la abstraccin escondiendo su estructura y secretos de comportamiento. 2. visin interna (implementacin), que abarca el cdigo que se ofrece en la interface de la clase. Las clases son declaraciones o abstracciones de objetos, lo que significa, que una clase es la definicin de un objeto. Cuando se programa un objeto y se definen sus caractersticas y funcionalidades, realmente se programa una clase. Las clases son agrupaciones de objetos que contienen las mismas caractersticas, en el cual se le colocan sus atributos y mtodos.

Ejemplo: una lavadora, su clase es lnea blanca, un pantaln, su clase es ropa.

d. Objeto Un objeto es una cosa tangible, algo a que se puede aprehender intelectualmente o algo hacia lo que se puede dirigir una accin o pensamiento. Un objeto representa un item individual e identificable, o una entidad real o abstracta, con un papel definido en el dominio del problema Un objeto tiene: o Estado o Comportamiento o Identidad La estructura y el comportamiento de objetos similares se definen en sus clases comunes. El trmino objeto y ejemplo (instance) de una clase son intercambiables. Son todas las cosas que existen, que se pueden ver, tocar o sentir, estos conforman las clases, los objetos tienen caractersticas (atributos) y funciones (mtodos). Algunos ejemplos son: mesa, silla, casa, baln, aire, etc.

Estado de un objeto El estado de un objeto abarca todas las propiedades del objeto, y los valores actuales de cada una de esas propiedades. Las propiedades de los objetos suelen ser estticas, mientras los valores que toman estas propiedades cambian con el tiempo. El hecho de que los objetos tengan estado implica que ocupan un espacio fsico o en la memoria del ordenador. El estado de un objeto est influido por la historia del objeto. No deben confundirse los objetos, que existen en el tiempo, son mutables, tienen estado, pueden ser creados, destruidos y compartidos..., con los valores (los asignados a una variable, por ejemplo) que son cantidades con las propiedades de ser atemporales, inmutables. El estado de un objeto representa el efecto acumulado de su comportamiento. Identidad de un objeto Identidad es la propiedad de un objeto que lo lleva a distinguirse de otros. Comportamiento de un objeto Comportamiento es como un objeto acta y reacciona, en trminos de sus cambios de estado y de los mensajes que intercambia. El comportamiento de un objeto representa su actividad externamente visible y testable. Son las operaciones que una clase realiza (llamadas tambin mensajes) las que dan cuenta de como se comporta la clase. Por operacin se denota el servicio que una clase ofrece a sus clientes. Un objeto puede realizar cinco tipos de operaciones sobre otro, con el propsito de provocar una reaccin: Modificador: altera el estado de un objeto. Selector: accede al estado de un objeto, sin alterarlo. Iterador: permite a todas las partes de un objeto ser accedidas en un orden. Constructor: crea un objeto y/o inicializa su estado.

Destructor: libera el estado de un objeto y/o destruye el objeto.

Relaciones entre clases Representan tipos de comparticin entre clases o relaciones semnticas. Asociacin. Indica relaciones de mandato bidireccionales. Conlleva dependencia semntica y no establece una direccin de dependencia. Tienen cardinalidad. Herencia. Por esta relacin una clase (subclase) comparte la estructura y/o comportamiento definidos en una (herencia simple) o ms (herencia mltiple) clases, llamadas superclases. Representa una relacin del tipo "es un" entre clases. Una subclase aumenta o restringe el comportamiento o estructura de la superclase (o ambas cosas). Agregacin. Representa una relacin del tipo "tener un" entre clases. Cuando la clase contenida no existe independientemente de la clase que la contiene se denomina agregacin por valor y adems implica contenido fsico, mientras que si existe independientemente y se accede a ella indirectamente, es agregacin por referencia. Uso. Es un refinamiento de la asociacin donde se especifica cul es el cliente y cual el servidor de ciertos servicios, permitiendo a los clientes acceder slo a las interfaces pblicas de los servidores, ofreciendo mayor encapsulacin de la informacin. Ejemplificacin. Se usa en lenguajes que soportan la declaracin de clases parametrizadas. Representa las relaciones entre las clases parametrizadas, que admiten parmetros formales, y las clases obtenidas cuando se concretan estos parmetros formales, ejemplificados o inicializados con un ejemplo. Metaclases. Son clases cuyos ejemplos son a su vez clases. Relaciones entre clases y objetos Todo objeto es el ejemplo de una clase, y toda clase tiene 0 ms objetos. Mientras las clases son estticas, con semntica, relaciones y existencia fijas previamente a la ejecucin de un programa, los objetos se crean y destruyen rpidamente durante la actividad de una aplicacin. El diseo de clases y objetos es un proceso incremental e iterativo. Debe asegurar la optimizacin en los parmetros: Acoplamiento: Grado de acoplamiento entre mdulos. Cohesin: Mide el grado de conectividad entre elementos de un mdulo, y entre objetos de una clase.

Suficiencia: Indica que las clases capturan suficientes caractersticas de la abstraccin para conseguir un comportamiento e interaccin eficiente y con sentido. Completitud: Indica que la interface de la clase captura todo el significado caracterstico de una abstraccin, escrito en el mnimo espacio. Primitividad: Las operaciones deben implementarse si dan acceso a una representacin fundamental de la abstraccin. Cuales son operaciones primitivas y cules no (se pueden realizar a partir de otras) es un asunto subjetivo y afecta a la eficiencia en la implementacin.

2.2 Instanciacin de una clase. Una vez que tenemos una clase definida, lo nico de lo que disponemos es de una especie de plantilla o molde a partir del cual podemos crear objetos en memoria. Para crear esos objetos podemos hacerlo de dos formas, pero como veremos siempre ser mediante la instruccin new que es la encargada de crear el objeto en la memoria y asignar la direccin del mismo a la variable usada en la parte izquierda de la asignacin. a. Declarar primero la variable y despus instanciarla Lo primero que tenemos que hacer es declarar una variable del tipo que queremos instanciar, esto lo hacemos de la misma forma que con cualquier otro tipo de datos: Cliente cli1; Con esta lnea de cdigo lo que estamos indicando al compilador es que tenemos intencin de usar una variable llamada cli1 para acceder a una clase de tipo Cliente. Esa variable, cuando llegue el momento de usarla, sabr todo lo que hay que saber sobre una clase Cliente, pero hasta que no tenga una "referencia" a un objeto de ese tipo no podremos usarla. La asignacin de una referencia a un objeto Cliente la haremos usando la instruccin new seguida del nombre de la clase: cli1 = new Cliente(); A partir de este momento, la variable cli1 tiene acceso a un nuevo objeto del tipo Cliente, por tanto podremos usarla para asignarle valores y usar cualquiera de los miembros que ese tipo de datos contenga: cli1.Nombre = "Antonio"; cli1.Apellidos = "Ruiz Rodrguez"; cli1.Saludar(); Declarar e instanciar en un solo paso.

La otra forma de instanciar una clase es hacindolo al mismo tiempo que la declaramos. En Java esto se hace como si uniramos la declaracin y la instanciacin en una sola instruccin: Cliente cli2 = new Cliente(); De esta forma se asignar a la variable cli2 una referencia a un nuevo objeto creado en la memoria, el cual ser totalmente independiente del resto de objetos creados con esa misma clase. El resumen del proceso hasta aqu descrito puede ser sintetizado como sigue:
Programador Compilador Ejecucin Ejecucin Declaracin & definicin de clase (en programa fuente) Funcin-clase (en fichero ejecutable) Objeto-clase (en memoria) Objeto-instancia (en memoria)

2.3 Referencia al objeto actual. Una variable de tipo objeto es una referencia (puntero) a un objeto: A a1= new A(); A a2= new A(); A a3= a2; a1.Set(1,2); a2.Set(5,6); a3.Set(8,9); a1.Print(); // 1 2 a2.Print(); // 8 9 a3.Print(); // 8 9 Muchos mtodos de un objeto necesitan acceder a los datos miembros de este, y a otras propiedades del objeto. Por este motivo es que el lenguaje Java junto a la ejecucin de un mtodo pasa como argumento la referencia del objeto que est ejecutando el miembro. Para referirnos explcitamente a esta referencia desde el mtodo utilizamos la palabra reservada this. Que no es otra cosa que una referencia al objeto que est ejecutando al mtodo. Dentro de un mtodo, el identificador this contiene una referencia al objeto con que se invoc este mtodo.

2.4 Mtodos: declaracin, mensajes, paso de parmetros, retorno de valores. Los mtodos o funciones miembro se definen dentro de la clase a la que pertenecen y constituyen la interfaz o forma de acceder a la estructura interna de los objetos es decir a los datos privados. Los mtodos definen cual son las operaciones que se pueden realizar con los atributos de los objetos de la clase. La ejecucin de un programa orientado a objetos consiste, en recibir, interpretar y responder unos objetos a los mensajes que envan otros objetos. En P.O.O. un mensaje est asociado siempre con un mtodo, de manera que cuando un objeto recibe un mensaje la respuesta a ese mensaje es ejecutar el mtodo asociado. Declaracin o cabecera: a. Modo de acceso: Especfica el tipo de acceso permitido indicando que usuarios de la clase podrn acceder a ese mtodo, los mtodos son la nica forma de acceso a los atributos privados. Por defecto los mtodos tienen proteccin paquete, es decir son accesibles desde cualquier clase que pertenezca al mismo paquete. Todas las clases de un mismo fichero .java pertenecen a un mismo paquete. Public: Accesible desde cualquier otra clase. Package: Accesible slo desde el mismo paquete. Protected: Se comporta como un mtodo pblico para los mtodos del mismo paquete o de las subclases y para el resto como un mtodo privado. Prvate: Slo accesible a travs de mtodos de la propia clase. b. Retorno de valores: Un mtodo puede devolver un valor a quien lo llama o no devolver nada. El valor devuelto por un mtodo puede ser de un tipo primitivo de datos o una referencia, pero nunca puede devolver ms de un valor. El valor de retorno nunca puede ser un objeto de una superclase, s de la misma clase o de una subclase. Si el mtodo no devuelve nada el tipo devuelto por el mtodo es el tipo void. c. Paso de parmetros a una funcin o mtodo. Los parmetros de una funcin son variables locales que se inicializan en el momento de la llamada al mtodo. Fuera de la funcin no se conocen y no pueden ser accedidas. Se crean al entrar en la funcin y se destruyen al salir de ella. El paso de parmetros o argumentos a las funciones se puede hacer de dos formas. Paso por valor y Paso por referencia Accesibilidad, mbito y miembros compartidos

Accesibilidad y mbito son dos conceptos que estn estrechamente relacionados. Aunque en la prctica tienen el mismo significado, ya que lo que representan es la "cobertura" o alcance que tienen los miembros de las clases e incluso de las mismas clases que definamos. Si bien cada uno de ellos tienen su propia "semntica", tal como podemos ver a continuacin: mbito: o Es el alcance que la definicin de un miembro o tipo puede tener. Es decir, cmo podemos acceder a ese elemento y desde dnde podemos accederlo. o El mbito de un elemento de cdigo est restringido por el "sitio" en el que lo hemos declarado. Estos sitios pueden ser: mbito de bloque: Disponible nicamente en el bloque de cdigo en el que se ha declarado. Por ejemplo, si declaramos una variable dentro de un bucle for o un if, esa variable solo estar accesible dentro de ese bloque de cdigo. mbito de procedimiento: Disponible nicamente dentro del procedimiento, (funcin o propiedad), en el que se ha declarado. Cualquier variable declarada dentro de un procedimiento (mtodo o propiedad) solo estar accesible en ese procedimiento y en cualquiera de los bloques internos a ese procedimiento. mbito de mdulo: Disponible en todo el cdigo de la clase o la estructura donde se ha declarado. Las variables con mbito a nivel de mdulo, tambin estarn disponibles en los procedimientos declarados en el mdulo (clase o estructura) y por extensin a cualquier bloque dentro de cada procedimiento. mbito de espacio de nombres: Disponible en todo el cdigo del espacio de nombres. Este es el nivel mayor de cobertura o alcance, aunque en este nivel solo podemos declarar tipos como clases, estructuras y enumeraciones, ya que los procedimientos solamente se pueden declarar dentro de un tipo. Por regla general, cuando declaramos una variable en un mbito, dicha variable "ocultar" a otra que tenga el mismo nombre y est definida en un bloque con mayor alcance, aunque veremos que en C# existen ciertas restricciones dependiendo de dnde declaremos esas variables. En VB6 los mbitos disponibles solamente eran los de mdulo y procedimiento, en estos casos, cualquier variable declarada en un procedimiento oculta a una definida en un mdulo. En Visual C# 2005 podemos definir una variable dentro de un bloque de cdigo, en ese caso dicha variable solo ser accesible dentro de ese bloque. Aunque, como veremos a continuacin, en un procedimiento solamente podremos definir variables que no se oculten entre s, estn o no dentro de un bloque de cdigo.

Ejemplos mbito de bloque En los siguientes ejemplos veremos cmo podemos definir variables para usar solamente en el bloque en el que estn definidas. Los bloques de cdigo en los que podemos declarar variables son los bucles, (for,foreach, do, while), y los bloques condicionales, (if, switch), o en cualquier otro bloque formado por un par de llaves. Por ejemplo, dentro de un procedimiento podemos tener varios de estos bloques y por tanto podemos definir variables "internas" a esos bloques: int n = 3; // for (int i = 1; i <= 10; i++ ) { int j = 0; j += 1; if( j < n ) { //... } } // if( n < 5 ) { int j = n * 3; } // do { int j = 0; for(int i = 1; i <= n; i++) { j += i; } if( j > 10 ) break; }while(true);

La variable n estar disponible en todo el procedimiento, por tanto podemos acceder a ella desde cualquiera de los bloques. En el primer bucle for, definimos la variable i como la variable a usar de contador, esta variable solamente estar accesible dentro de este bucle for. Lo mismo ocurre con la variable j. En el primer if definimos otra variable j, pero esa solo ser accesible dentro de este bloque y por tanto no tiene ninguna relacin con la definida en el bucle for anterior. En el bucle do volvemos a definir nuevamente una variable j, a esa variable la podemos acceder solo desde el propio bucle do y cualquier otro bloque de cdigo interno, como es el caso del bucle for, en el que nuevamente declaramos una variable llamada i, que nada tiene que ver con el resto de variables declaradas con el mismo nombre en los otros bloques. Nota: El cdigo del bucle do mostrado anteriormente se convertir en un bucle infinito, ya que la variable j siempre se pone a cero en cada repeticin del bucle do/while, por tanto solo hay que tomarlo como un ejemplo para probar lo del mbito de las variables. Esta restriccin solo es aplicable a las variables declaradas en el procedimiento, ya que si declaramos una variable a nivel de mdulo, no habr ningn problema para usarla dentro de un bloque, esto es as porque en un procedimiento podemos declarar variables que se llamen de la misma forma que las declaradas a nivel de mdulo, aunque stas ocultarn a las del "nivel" superior. mbito de procedimiento Las variables declaradas en un procedimiento tendrn un mbito o cobertura que ser el procedimiento en el que estn declaradas, y como hemos visto, ese mbito incluye tambin cualquier bloque de cdigo declarado dentro del procedimiento. Estas variables ocultarn a las que se hayan declarado fuera del procedimiento, si bien, dependiendo del tipo de mdulo, podremos acceder a esas variables "externas" indicando el nombre completo del mdulo o bien usando la instruccin this seguida del nombre de la variable. Pero mejor vemoslo con un ejemplo. En el siguiente cdigo, definimos una clase en la que tenemos un campo llamado Nombre, tambin definimos un mtodo en el que internamente se utiliza una variable llamada Nombre, para acceder a la variable declarada en la clase, tendremos que usar la instruccin o palabra clave this. public class Cliente {

public string Nombre = "Juan"; public string Mostrar() { string Nombre = "Pepita"; return "Externo= " + this.Nombre + ", interno= " + Nombre; } } mbito de mdulo Cuando hablamos de mdulos, nos estamos refiriendo a una clase, a una estructura o a cualquier otro tipo de datos que nos permita el lenguaje. En estos casos, las variables declaradas dentro de un tipo de datos sern visibles desde cualquier parte de ese tipo, siempre teniendo en cuenta las restricciones mencionadas en los casos anteriores. mbito de espacio de nombres Los espacios de nombres son los contenedores de tipos de datos de mayor nivel, y sirven para contener definiciones de clases, estructuras, enumeraciones y delegados. Cualquier tipo definido a nivel de espacio de nombres estar disponible para cualquier otro elemento definido en el mismo espacio de nombres. Al igual que ocurre en el resto de mbitos "inferiores", si definimos un tipo en un espacio de nombres, podemos usar ese mismo nombre para nombrar a un procedimiento o a una variable, en cada caso se aplicar el mbito correspondiente y, tal como vimos anteriormente, tendremos que usar nombres nicos para poder acceder a los nombres definidos en niveles diferentes. Accesibilidad La accesibilidad es la caracterstica que podemos aplicar a cualquiera de los elementos que definamos en nuestro cdigo. Dependiendo de la accesibilidad declarada tendremos distintos tipos de accesos a esos elementos. Los modificadores de accesibilidad los podemos usar tanto en clases, estructuras, interfaces, enumeraciones, delegados, eventos, mtodos, propiedades y campos. Aunque no sern aplicables en espacios de nombres (Namespace) ni en los miembros de las interfaces y enumeraciones. Accesibilidad de las variables en los procedimientos

Las variables declaradas dentro de un procedimiento solo son accesibles dentro de ese procedimiento, en este caso solo se puede aplicar el mbito privado, aunque no podremos usar la instruccin private, sino declararlas de la forma habitual. Las accesibilidades predeterminadas La accesibilidad de un tipo, variable o procedimiento en la que no hemos indicado el modificador de accesibilidad depender del sitio en el que lo hemos declarado. Por ejemplo, las clases y estructuras definidas a nivel de un espacio de nombres solo pueden ser declaradas como public o internal, y si no llevan un modificador de accesibilidad, por defecto sern internal, es decir sern visibles en todo el proyecto actual. Por otro lado, las interfaces y enumeraciones por defecto sern pblicas. Cuando la clase, estructura, interfaz o enumeracin est definida dentro de otro tipo, la accesibilidad predeterminada ser private, pero admitirn cualquiera de los modificadores, salvo las interfaces y enumeraciones que no pueden ser protected. Por otro lado, los miembros de esos tipos tambin permiten diferentes niveles de accesibilidad, en el caso de las interfaces y enumeraciones, siempre sern pblicos, aunque no se permite el uso de esa instruccin. Los miembros de as clases y estructuras sern privados de forma predeterminada, en el caso de las clases, en esos miembros podemos indicar cualquiera de los cinco niveles de accesibilidad, mientras que en las estructuras no podremos declarar ningn miembro como protected o protected internal, ya que una estructura no puede usarse como base de otro tipo de datos. Anidacin de tipos Tal como hemos comentado en la seccin, podemos declarar tipos dentro de otros tipos, por tanto el mbito y accesibilidad de esos tipos dependen del mbito y accesibilidad del tipo que los contiene. Por ejemplo, si declaramos una clase con acceso internal, cualquier tipo que esta clase contenga siempre estar supeditado al mbito de esa clase, por tanto si declaramos otro tipo interno, aunque lo declaremos como public, nunca estar ms accesible que la clase contenedora, aunque en estos casos no habr ningn tipo de confusin, ya que para acceder a los tipos declarados dentro de otros tipos siempre tendremos que indicar la clase que los contiene. Miembros compartidos (estticos) Por otro lado, los miembros compartidos, (o miembros estticos), de una clase o tipo, son elementos que no pertenecen a una instancia o copia en memoria particular, sino que pertenecen al propio tipo y por tanto siempre estn accesibles o disponibles, dentro del nivel del mbito y accesibilidad que les hayamos aplicado, y su tiempo de vida es el mismo que el de la aplicacin.

Parmetros Un parmetro es una variable que puede pasar su valor a un procedimiento desde el principal o desde otro procedimiento. Existen ocasiones en que es necesario mandar al procedimiento ciertos valores para que los use en algn proceso. Estos valores que se pasan del cuerpo principal del programa al procedimiento se llaman parmetros. Entonces la declaracin completa de un procedimiento es: static void NomProc(lista de parmetros) { cuerpo de instrucciones; }; Reglas para el uso de parmetros 1. Cuando se usan variables como parmetros, la variable que se manda debe ser declarada dentro del principal o del procedimiento de donde se est enviando. 2. La variable que se manda tiene un nombre, la que se recibe puede tener otro nombre. 3. La cantidad de variables que se envan deben ser igual en cantidad, orden y tipo a las variables que reciben. 4. La variable que se recibe tiene un mbito local dentro del procedimiento, es decir solo la puede usar ese procedimiento. Los parmetros se declaran en la cabecera de la declaracin de los mtodos. Al declararse el parmetro, se indica el tipo de dato y el identificador correspondiente. Los parmetros o argumentos de un constructor o de un mtodo pueden ser de cualquier tipo, ya sean tipos primitivos o referencias de objetos (en este caso debe indicarse el identificador de la clase correspondiente). Ejemplos de declaraciones de cabeceras de mtodos: a. public double devuelve() // Sin parametros { . . . return . . . ;} b. public void asigna(double x) // Un parametro, x de tipo double {...} c. public int elMayor(int a, int b) // Dos parametros, a y b de tipo int { . . . return . . . } d. public static double sumatorio (double [] v) // Un parametro, v, array real { . . . return . . . } e. public boolean caducado (Fecha fechaLimite) // Un parmetro de la clase Fecha { . . . return . . . } El identificador del parmetro se emplea slo dentro del mtodo para hacer referencia al argumento correspondiente y puede coincidir con el de un atributo de la misma clase. En

tal caso, se dice que oculta a la variable miembro. Esta tcnica suele emplearse en los constructores para inicializar una instancia. Por ejemplo en la clase Crculo: public class Circulo { int x, y, radio; public circulo(int x, int y, int radio) { ... } } La clase Circulo tiene tres atributos o variables miembro x, y y radio y un constructor con tres argumentos con los mismos identificadores que facilitan los valores iniciales a los atributos respectivamente. Los identificadores de los parmetros ocultan a las variables miembro dentro del cuerpo del constructor, de forma que x, y y radio dentro del constructor hacen referencia a los parmetros y no a las variables miembro. Para acceder a las variables miembro, es necesario emplear la palabra reservada this que referencia a la instancia que est siendo inicializada por el constructor. public class Circulo { int x, y, radio; public Circulo(int x, int y, int radio) { this.x = x; // this.x hace referencia al atributo x // x hace referencia al parmetro x this.y = y; // this.y hace referencia al atributo y // y hace referencia al parmetro y this.radio = radio; // this.radio hace referencia al atributo radio // radio hace referencia al parmetro radio } } Normalmente dentro del cuerpo del mtodo de una clase puede hacerse referencia directa a las variables miembro de las instancias. Salvo en el caso del ejemplo anterior en el que las variables miembro estn ocultas. Por otro lado, los parmetros de un mismo mtodo no puede compartir el mismo identificador (no pueden coincidir) con el de una variable local. El siguiente cdigo genera un error de compilacin: public void asigna(double x) { // Un parametro, x de tipo double double x; // Error de compilacion ...}

2.5 Constructores y destructores: declaracin, uso y aplicaciones. Es el punto de inicio de una clase. Cada vez que creamos un nuevo objeto en memoria estamos llamando al constructor de la clase. En el constructor de una clase podemos incluir el cdigo que creamos conveniente, pero realmente solamente deberamos incluir el que realice algn tipo de inicializacin, en caso de que no necesitemos realizar ningn tipo de inicializacin, no es necesario definir el constructor, ya que el propio compilador lo har por nosotros. Esto es as porque todas las clases deben implementar un constructor, por tanto si nosotros no lo definimos, lo har el compilador. Si nuestra clase Cliente tiene un campo para almacenar el crdito del objeto podemos hacer algo como esto: class Cliente { private Sstring nombre; private String apellidos; private DateTime fechaCreacion; private float credito;

public Cliente() { crdito= 10000; } } De esta forma podemos crear un nuevo Cliente y acto seguido comprobar el valor del crdito para saber cul es el crdito que tiene dicho cliente. En los constructores tambin podemos hacer las inicializaciones que, por ejemplo permitan a la clase a conectarse con una base de datos, abrir un fichero o cargar una imagen grfica, etc.

Constructores parametrizados De la misma forma que podemos tener mtodos sobrecargados, tambin podemos tener constructores sobrecargados, ya que en java el constructor es como una funcin con un tratamiento especial que devuelve un nuevo objeto.

La ventaja de tener constructores que admitan parmetros es que podemos crear nuevos objetos indicando algn parmetro, por ejemplo un fichero a abrir o, en el caso de la clase Cliente, podemos indicar el nombre y apellidos del cliente o cualquier otro dato que creamos conveniente. Para comprobarlo, podemos ampliar la clase definida anteriormente para que tambin acepte la creacin de nuevos objetos indicando el nombre y los apellidos del cliente. class Cliente; { private Sstring nombre; private String apellidos; private DateTime fechaCreacion; private float credito;

public Cliente() { crdito= 10000; } public Cliente(string elNombre, string losApellidos) { Nombre = elNombre; Apellidos = losApellidos; FechaCreacion = DateTime(); } } Teniendo esta declaracin de la clase Cliente, podemos crear nuevos clientes de dos formas: Cliente c1 = new Cliente(); Cliente c2 = new Cliente("Jose", "Snchez"); Como podemos comprobar, en ciertos casos es ms intuitiva la segunda forma de crear objetos del tipo Cliente, adems de que as nos ahorramos de tener que asignar individualmente los campos Nombre y Apellidos. Esta declaracin de la clase Cliente la podramos haber hecho de una forma diferente. Por un lado tenemos un constructor "normal" (no recibe parmetros) en el que asignamos el

crdito y por otro el constructor que recibe los datos del nombre y apellidos. En ese segundo constructor tambin asignamos la fecha de creacin, ya que, se instancie como se instancie la clase, nos interesa saber siempre la fecha de creacin. Tal como hemos comentado, si nosotros no definimos un constructor, lo har el propio compilador y cuando lo hace automticamente, siempre es un constructor sin parmetros. Pero hay ocasiones en las que nos puede interesar que no exista un constructor sin parmetros, por ejemplo, podemos crear una clase Cliente que solo se pueda instanciar si le pasamos, por ejemplo el nmero de identificacin fiscal, (NIF), en caso de que no se indique ese dato, no podremos crear un nuevo objeto Cliente; de esta forma nos aseguramos de que el NIF siempre est especificado. Seguramente por ese motivo, si nosotros definimos un constructor con parmetros, el lenguaje no lo crea automticamente sin parmetros. Por tanto, si definimos un constructor con parmetros en una clase y queremos que tambin tenga uno sin parmetros, lo tenemos que definir nosotros mismos, aunque no es necesario que el constructor sin parmetros ejecute cdigo, puede estar declarado sin ms. El destructor: El punto final de la vida de una clase De la misma forma que una clase tiene su punto de entrada o momento de nacimiento en el constructor, tambin tienen un sitio que se ejecutar cuando el objeto creado en la memoria ya no sea necesario, es decir, cuando acabe la vida del objeto creado. En java el programador no tiene que colocar un destructor debido a que el recolector de basura elimina los objetos que ya no son referenciados. En lenguajes como C# se llama igual que la clase pero precedida del carcter ~ y no puede tener ningn modificador de visibilidad. Y solo es necesario definirlo si nuestra clase utiliza algn tipo de recurso, por tanto no es necesario definirlo si no tenemos que liberar expresamente algn recurso asignado en el constructor. La definicin del destructor de nuestra clase Cliente poda ser algo como esto: ~Cliente() { } El que un destructor no sea accesible externamente es por la sencilla razn de que es el propio CLR el que se encarga de gestionar la destruccin de los objetos que ya no son utilizados. Debido a que no es posible invocar al destructor desde el objeto creado en la memoria, debemos implementar explcitamente un mtodo que sea el que se encargue de hacer esa limpieza de los recursos utilizados por nuestra clase, ese mtodo suele tener el nombre Close o Dispose, en este ltimo caso, lo que se recomienda es que nuestra clase

implemente la interfaz IDisposable con idea de que si no se llama expresamente al mtodo que libera la memoria, sea el propio runtime del .NET Framework el que lo llame cuando el objeto ya no sea necesario mantenerlo en memoria. Es importante saber que los destructores no se llaman de forma inmediata, es decir, es posible que un objeto ya no se est usando, pero el CLR no llamar al destructor hasta que no lo crea conveniente, por tanto si nuestra clase utiliza recursos externos es imperativo que el usuario que utilice nuestra clase llame de forma explcita al mtodo que hayamos definido para liberar esos recursos. 2.6 Sobrecarga de mtodos La sobrecarga de funciones, es una caracterstica que nos permite tener una misma funcin con diferentes tipos de parmetros, ya sea en nmero o en tipo. Supongamos que queremos tener dos funciones (o ms) que nos permitan hacer operaciones con diferentes tipos de datos, y que, segn el tipo de datos usado, el valor que devuelva sea de ese mismo tipo. En este ejemplo, tenemos dos funciones que se llaman igual pero una recibe valores de tipo entero y la otra de tipo doble: int suma(int uno, int dos) { return uno + dos; } double suma(double uno, double dos) { return uno + dos; } Como podemos comprobar las dos funciones tienen el mismo nombre, pero tanto una como otra reciben parmetros de tipos diferentes. Siempre podremos crear sobrecarga de funciones si los parmetros son de distinto tipo o tienen un nmero diferente de parmetros, ya que si solo se diferencian por el tipo del valor devuelto, no podemos crear sobrecarga. La siguiente declaracin no crear una sobrecarga de la funcin suma, ya que el tipo de parmetros es el mismo que el mostrado anteriormente y solo se diferencia en el tipo del valor devuelto, por tanto obtendremos un error del compilador indicndonos que ya existe una funcin suma con ese mismo tipo de parmetros. float suma(int uno, int dos)

{ return uno + dos; } Debemos tener en cuenta que java distingue entre maysculas y minsculas, por tanto, una funcin llamada suma ser diferente de otra llamada Suma (con la ese en maysculas). Tambin podemos tener sobrecargas usando una cantidad diferente de parmetros, aunque stos sean del mismo tipo que otra funcin previamente definida, pero al tener un nmero diferente de parmetros, no existir ningn conflicto. Por ejemplo, podemos aadir esta declaracin al cdigo anterior sin que exista ningn tipo de error, ya que esta nueva funcin recibe tres parmetros en lugar de dos: int suma(int uno, int dos, int tres) { return uno + dos + tres; } Cuando, desde el IDE queremos usar los mtodos sobrecargados, nos mostrar una lista de opciones indicndonos las posibilidades de sobrecarga que existen y entre las que podemos elegir. 2.7 Sobrecarga de operadores: concepto y utilidad, operadores unarios y binarios La sobrecarga de operadores es aquella en la cual un operador puede ser utilizado para realizar diferentes tipos de operaciones, dependiendo de los parmetros que se le indiquen, por ejemplo + (sumar, concatenar y positivo/negativo). Java no soporta sobrecarga de operadores, aunque el sistema internamente la utiliza, pero est ocultada al programador, por ejemplo si te fijas al hacer un int ejemplo=2+1; En java eso es vlido y le asigna un 3 a la variable ejemplo la funcionalidad fue sumar, sin embargo en este: String ejemplo="hola"+"mundo"; El operador + se utiliza con otra finalidad: Concatenar, Java si usa la sobrecarga de operadores, pero esta oculta para el programador, sea no te permite usarla. Porque? Bsicamente para no llevar a confusin, imagina que defines una clase llamada "sobreEscribe" en la cual sobrecargaras el operador suma y le asignars tu propia forma de trabajar por ejemplo sumar fracciones y ms tarde defines la clase "fracciones"

heredando la clase "sobreEscribe" el resultado sera que en la clase "fracciones" el operador suma cambiar su comportamiento. Si llegase ahora un programador externo y revisar la clase fracciones podra confundirse y creer que este operador mantiene el comportamiento normal, para saber que tiene el comportamiento actual tendra que ir a revisar "sobreEscribe", ahora imagina que esta herencia se realiza entre varias clases, sera muy difcil saber si realmente se est cambiando el comportamiento del operador suma o no. Esta es una de las razones ms fuertes por las cuales Java no soporta la sobrecarga de operadores bsicamente para no llevar a confusin y al fin y al cabo no es necesaria, puedes utilizar tus propios mtodos Ejemplo de sobrecarga del operador suma en C Si tenemos una clase ComplejoC que representa un complejo, para poder sumar dos de estas clases simplemente poniendo un +, como con cualquier tipo bsico de C++, debemos sobrecargar el operador +, darle una nueva funcionalidad. La sobrecarga de un operador suma se hace de la siguiente manera class ComplejoC { public: // Permite sumar un ComplejoC con un double ComplejoC operator + (double sumando); // Permite sumar un ComplejoC con un array ComplejoC operator + (const double sumando[]); // Permite sumar dos ComplejoC entre s. ComplejoC operator + (const ComplejoC &sumando); }; Aqu estamos redefiniendo tres operadores suma para que nos permita sumar a nuestra clase ComplejoC cosas como un double, un array de double (que supondremos contiene dos double, aunque no tenemos forma de comprobarlo) y otra clase ComplejoC. En estas funciones hemos puesto const en los parmetros para no poder cambiarlos dentro del cdigo. En la tercera funcin pasamos ComplejoC por referencia (el &), para evitar que se hagan copias innecesarias. En la primera funcin no es necesario nada de esto, puesto que es un simple double. En la segunda, ponemos const para no poder modificar el array, pero no es necesaria la referencia, puesto que los arrays son punteros. A la hora de implementar debemos tener cuidado con los const que hemos puesto. Por ejemplo, en el tercer operador +, recibimos un sumando que es const. El cdigo que implementemos dentro no puede modificar dicho sumando, ni puede llamar a ningn

mtodo de ese sumando que no est declarado como const. Si lo intentamos, el compilador dar error. Supongamos que ComplejoC tiene un atributo double x (parte real) y un mtodo dameX() para obtener dicho atributo, este mtodo debe estar declarado const para poder llamarlo desde nuestro operator +. Ms o menos esto: class ComplejoC { public: // Atencin al const del final. Sin el no podemos llamar a sumando.dameX(). double dameX() const; }; De forma que en el operator + podemos llamar a sumando.dameX(). Una vez implementados estos mtodos, podemos hacer operaciones como ComplejoC a; ComplejoC b; // Aprovechando la primera sobrecarga b = a + 1.0; // Aprovechando la segunda sobrecarga double c[] = {1.0, 2.0}; b = a + c; // Aprovechando la tercera sobrecarga b = a + b; Cuando el compilador lee a + 1.0, lo interpreta como a.operator + (1.0), es decir, la llamada al operador suma al que se le pasa como parmetro un double. De la misma forma sucede con los otros dos operadores suma. Sin embargo, esto nos da un pequeo problema. Qu pasa si ponemos 1.0 + a?. Debera ser lo mismo, pero al compilador le da un pequeo problema. Intenta llamar al mtodo operator + de 1.0, que no existe, puesto que 1.0 ni es una clase ni tiene mtodos. Para solucionar este problema tenemos la sobrecarga de operadores globales. Sobrecarga de operadores suma globales Un operador global es una funcin global que no pertenece a ninguna clase y que nos indica cmo operar con uno o dos parmetros (depende del tipo de operador). En nuestro ejemplo de las sumas, para poder poner los sumandos al revs, deberamos definir las siguientes funciones globales: ComplejoC operator + (double sumando1, const ComplejoC &sumando2); ComplejoC operator + (double sumando1[], const ComplejoC &sumando2);

Estas funciones le indican al compilador cmo debe sumar los dos parmetros y qu devuelve. Con ellas definidas e implementadas, ya podemos hacer b = 1.0 + a; // c era un array de double b = c + a; Esta sobrecarga es especialmente til cuando tratamos con una clase ya hecha y que no podemos modificar. Por ejemplo, cout es de la clase ostream y no podemos modificarla, sin embargo nos sera de utilidad sobrecargar el operador << de ostream de forma que pueda escribir nuestros nmeros complejos. La siguiente llamada nos dar error mientras no redefinamos el operator << de ostream. cout << a << endl; // a es un ComplejoC Con la sobrecarga de operadores globales podemos definir la funcin ostream &operator << (ostream &salida, const ComplejoC &valor); Con esta funcin definida, el complejo se escribir en pantalla como indique dicha funcin. Esta funcin deber escribir la parte real e imaginaria del complejo en algn formato, utilizando algo como salida << valor.dameX() << " + " << valor.dameY() << "j"; El operador devuelve un ostream, que ser un return cout. De esta forma se pueden encadenar las llamadas a cout de la forma habitual. cout << a << " + " << b << endl; Primero se evala operator << (cout, a), que escribe a en pantalla y devuelve un cout, con lo que la expresin anterior quedara, despus de evaluar esto cout << " + " << b << endl; y as consecutivamente. Hay que tener en cuenta que estos operadores globales no son de la clase, as que slo pueden acceder a mtodos y atributos pblicos de la misma.

http://arantxa.ii.uam.es/~castells/docencia/poo/3-objetos.pdf

You might also like