You are on page 1of 7

Subclases y Herencia Los mtodos y variables que posee un objeto definen la clase a la cual pertenece.

Por ejemplo, todos los objetos de la clase A poseen los mtodos Set, Incx y Print y las variables x e y. En cambio los objetos de la clase Eslabon poseen el mtodo Encadenar y las variables next y a. Una variable de tipo Eslabon no puede contener una referencia a un objeto de la clase A. Eslabon e= new A(); // error de tipos Puede existir una clase B de objetos que poseen todos los mtodos y todas las variables de A, pero adems poseen otros mtodos y/o variables que no poseen los objetos de A. En ese caso se dice que B es una subclase de A. Los objetos de la clase B tambin pertenecen a la clase A. El principio es que todo el cdigo que se haya escrito para objetos de la clase A tambin funcionar con objetos de la clase B. Una subclase se define mediante: class B extends A { // variables que B agrega a A int z; // Mtodos que B agrega a A // Observe que B tambin posee x voidIncz() { z= z+x; } } Se dice que la clase B hereda todas las variables y mtodos de A. Tambin se dice que B se deriva de A o que A es la clase base para B. La jerarqua de clases permite apreciar fcilmente qu clases son subclases de otras.

Observe que todos los objetos pertenecen a la clase Object. Consideraciones importantes al usar subclases: y Una variable de la clase A, tambin puede contener referencias a objetos de la clase B, porque estos objetos pertenecen a la clase B y a la clase A. Este concepto se denomina proyeccin. A a;

a= new B(); // Proyeccin Se dice que A es el tipo esttico de la variable a y B es el tipo dinmico de a. El tipo esttico siempre se determina en tiempo de compilacin mientras que el tipo dinmico en general slo se puede conocer en tiempo de ejecucin y puede cambiar.

y y y y

Dada una variable a, Java slo permite invocar los mtodos y accesar las variables conocidas para el tipo esttico de a. a.Incx(); // Ok a.x; // Ok a.Incz(); // error, Incz no est definido para A Del mismo modo, Java slo permite asignar una expresin a una variable de tipo A si el tipo de la expresin es A o una subclase de A: B b= new A(); // error, el objeto no pertence a // la clase B A a= new B(); // Ok ... B b= a; // error, la clase esttica de a // no es una subclase de B.

y y y y y

Un objeto se puede convertir a una referencia de la clase B mediante un cast: A a=new B(); B b=(B)a; b.Incz(); // Ok ( (B)a ).Incz(); // Ok No todo objeto se puede convertir a la clase B. A a= new A(); ... B b=(B)a; // Ok, en compilacin, pero // error en tiempo de ejecucin Java chequea durante la ejecucin todas las conversiones explcitas (casts). Si el objeto no pertence a la clase a la cual se pretende convertir, entonces se produce una excepcin.

El operador instanceof Se puede consultar si un objeto pertenece a una clase mediante: Object obj; ... if (objinstanceof A) // obj pertenece a la clase A A a=(A)obj; // Ok, nunca hay error Los objetos de la clase B tambin son instancias de la clase A:

Object obj= new B(); if (objinstanceof A) // true A a= (A)obj; // Ok

El constructor en una subclase Los constructores no se heredan: class A { ... A(int ix, intiy){ ... }; } class B extends A { ... } B b= new B(1,2); // error, ningn // constructor calza El constructor de la clase base se puede invocar con super: class B extends A { ... B(int ix, intiy) { super(ix, iy); z= 0; } B(int ix, intiy, intiz) { super(ix, iy); z= iz; } B(B b) { z= b.z; // x=y=? super(b.x, b.y); // error, super debe ser } // la primera instruccin } La invocacin del constructor de A siempre debe ser la primera instruccin del constructor de B. El principio es que en B las componentes de la clase base (A) deben inicializarse antes que las componentes que se agregan en la clase B.

Redefinicin de Mtodos Un problema que tiene la clase B que hered de A es que el mtodo Print slo imprime los campos x e y: B b= new B(1, 2, 3); b.Print(); // 1 2 >8^(

Al declarar una clase B derivada de A, aparte de agregar campos y mtodos, tambin se pueden redefinir mtodos. Por ejemplo, para B se puede redefinir el mtodo Print: class B extends A { ... void Print() // Redefinicin { System.out.println(x+" "+y+" "+z); } } B b= new B(1, 2, 3); b.Print(); // 1 2 3 8^) El nmero y tipo de los parmetros del mtodo redefinido debe coincidir exactamente con los del mtodo original. Observe que el mtodo Print para la clase A no cambia: A a= new A(1, 2); a.Print(); // 1 2

Enlace dinmico Qu mtodo se invoca en el siguiente caso? A a= new B(1, 2, 3); a.Print(); // ? El tipo esttico de la variable a es la clase A en donde Print slo imprime x e y, por lo que una posible respuesta es que se invoca el mtodo definido en la clase A. Sin embargo, la respuesta correcta es que se invoca el mtodo definido para el tipo dinmico de la variable a. Es decir la clase ms especfica a la cual pertenece el objeto referenciado por la variable a. Esta clase es B. Por lo tanto se invoca el Print definido para la clase B y la salida ser: 123 Esta forma de enlazar el nombre de un mtodo con el cdigo que se ejecutar para un objeto determinado se denomina enlace dinmico, porque el mtodo que finalmente se invocar en general slo se conoce durante la ejecucin y no durante la compilacin.

Clases y Mtodos Abstractos Una clase abstracta es una clase que se introduce slo para que se deriven nuevas clases de ella, no para que se creen objetos con su nombre. Del mismo modo, un mtodo abstracto es un mtodo que se introduce para que sea redefinido en una clase derivada. Por ejemplo abstractclassGraphObj { int x, y; // La posicin central GraphObj(int ix, intiy)

{ x= ix; y= iy; } // constructor void Move(int dx, intdy) { x+= dx; y+= dy; } abstract void Paint(Graphics g); // Paint es abstracto } Esta clase no se puede usar para crear un objeto, por lo que lo siguiente es un error: GraphObjgf= new GraphObj(10,20); // error La idea es que slo se pueden crear objetos de clases derivadas de la clase anterior: class Line extends GraphObj { // x e y se heredan int ix, iy; GraphObj(intaix, intaiy, intafx, intafy) { super((aix+afx)/2, (aiy+afy)/2); ix= aix; iy= aiy; } void Paint(Graphics g) { g.DrawLine(xi,yi,x+(x-xi),y+(y-yi)); } // Move se hereda de GraphObj } // Ahoras! Line line= new Line(0,0, 10,20); El principio es que se use varias veces la clase abstracta para definir varias otras clases que poseen un conjunto comn de mtodos: Paint y Move. // Unacaja class Box extends GraphObj { int height, width; Box(int lx, intly, inthx, inthy) { super( ... ); // Ejercicio ... } void Paint(Graphics g) { ... // Ejercicio } }

Redefinicin parcial de mtodos Supongamos que ahora se desea introducir una caja con color. Este objeto grfico es similar a un caja sola. Por lo tanto derivamos la caja con color a partir de una caja simple. Conservamos casi todo, pero tenemos que redefinir Paint. An as podemos reutilizar el Paint de Box:

classColorBox extends Box { int color; // El mismo constructor ColorBox(int lx, intly, inthx, inthy, intacolor) { super(lx, hx, ly, hy); color= acolor; } void Paint() // Redefinicin { intsavecolor= g.currColor(); g.setColor(color); super.Paint(); // el Paint de Box g.setColor(savecolor); } } Al redefinir un mtodo, se puede invocar el mtodo de la clase base usando super con sus respectivos argumentos.

Clases, Mtodos y Campos finales Una clase final es una clase que no se puede derivar. Es decir no posee subclases. final class B extends A { ... } class C extends B // error B es final { ... } Un mtodo final es un mtodo que no se puede redefinir en una subclase de la clase en donde se defini. Por ejemplo el mtodo Move asociado a un objeto grfico se puede declarar final en la clase GraphObj mediante: final void Move(int dx, intdy) { x+= dx; y+= dy; } De esta forma este mtodo no podr ser redefinido posteriormente en las clases Line, Box o ColorBox. Unacampo final es una variable a la que no se puede asignar un valor. La variable se inicializa con un valor durante su declaracin, pero luego no puede cambiar. Cumple el papel de las constante de otros lenguajes, pero observe que en Java se trata de constantes dinmica cuyo valor se calcula en ejecucin.

Variables y mtodos de la clase

Los campos que se definen en una clase se denominan variables de instancia porque se encuentran en los objetos. En Java tambin se pueden definir variables de la clase. Este tipo de variables se encuentra en la clase y no en los objetos. Las variables de clase se definen usando el atributo static: class A { int iv; staticint cv; voidInc() { iv++; cv++; System.out.println(iv+" "+cv); } // Constructor para los objetos A() { iv=0; } // Inicializador de la clase static { cv=0; } } A a1= new A(); A a2= new A(); a1.Inc(); // 1 1 a2.Inc(); // 1 2 a1.Inc(); // 2 3 a1.Inc y a2.Inc incrementan las misma variable cv. Un mtodo static de la clase es un mtodo que slo accesa variables de la clase. Se definen usando el atributo static: staticvoid Inc2() { cv++; } staticvoid Inc3() { iv++; } // error iv es de un objeto staticvoid Inc4() { Inc(); // error Inc necesita un obj. Inc2(); // Ok, porque Inc2 es static }

You might also like