Вы находитесь на странице: 1из 16

TECNOLÓGICO NACIONAL DE MÉXICO

Instituto Tecnológico Superior de Valladolid


ITSVA

Ingeniería en Sistemas Computacionales

 Programación orientada a objetos

Resumen

Uitzil Aban María Rosa


18070065

MTI. Jesús Antonio Santos Tejero


TECNOLÓGICO NACIONAL DE MÉXICO

3.1 Definición: clase base, clase derivada


La herencia es una propiedad esencial de la Programación Orientada a Objetos que
consiste en la creación de nuevas clases a partir de otras ya existentes. Este término
ha sido prestado de la Biología donde afirmamos que un niño tiene la cara de su
padre, que ha heredado ciertas facetas físicas o del comportamiento de sus
progenitores.

La herencia es la característica fundamental que distingue un lenguaje orientado a


objetos, como el C++ o Java, de otro convencional como C, BASIC, etc. Java
permite heredar a las clases características y conductas de una o varias clases
denominadas base. Las clases que heredan de clases base se denominan
derivadas, estas a su vez pueden ser clases bases para otras clases derivadas. Se
establece así una clasificación jerárquica, similar a la existente en Biología con los
animales y las plantas.

La herencia ofrece una ventaja importante, permite la reutilización del código. Una
vez que una clase ha sido depurada y probada, el código fuente de dicha clase no
necesita modificarse. Su funcionalidad se puede cambiar derivando una nueva
clase que herede la funcionalidad de la clase base y le añada otros
comportamientos. Reutilizando el código existente, el programador ahorra tiempo y
dinero, ya que solamente tiene que verificar la nueva conducta que proporciona la
clase derivada.

Clase base
Supongamos que tenemos una clase que describe la conducta de una ventana muy
simple, aquella que no dispone de título en la parte superior, por tanto, no puede
desplazarse, pero si cambiar de tamaño.

La clase Ventana tendrá los siguientes miembros dato: la posición x e y de la


ventana, de su esquina superior izquierda y las dimensiones de la
ventana: ancho y alto.
TECNOLÓGICO NACIONAL DE MÉXICO

public class Ventana {


protected int x;
protected int y;
protected int ancho;
protected int alto;
public Ventana(int x, int y, int ancho, int alto) {
this.x=x;
this.y=y;
this.ancho=ancho;
this.alto=alto;
}
Las funciones miembros, además del constructor serán las siguientes: la
función mostrar que simula una ventana en un entorno gráfico, aquí solamente nos
muestra la posición y las dimensiones de la ventana.
public void mostrar(){
System.out.println("posición : x="+x+", y="+y);
System.out.println("dimensiones : w="+ancho+", h="+alto); }
La función cambiarDimensiones que simula el cambio en la anchura y altura de la
ventana.

public void cambiarDimensiones(int dw, int dh){


ancho+=dw;
alto+=dh; }

Clase derivada

Incrementamos la funcionalidad de la clase Ventana definiendo


una clase derivada denominada VentanaTitulo. Los objetos de
dicha clase tendrán todas las características de los objetos de la
clase base, pero además tendrán un título, y se podrán desplazar.
TECNOLÓGICO NACIONAL DE MÉXICO

La clase derivada heredará los miembros dato de la clase base y las funciones
miembros, y tendrá un miembro dato más, el título de la ventana.

public class VentanaTitulo extends Ventana{

protected String titulo;

public VentanaTitulo(int x, int y, int w, int h, String nombre) {

super(x, y, w, h);

titulo=nombre; }

extends es la palabra reservada que indica que la clase VentanaTitulo deriva, o es


una subclase, de la clase Ventana.

La primera sentencia del constructor de la clase derivada es una llamada al


constructor de la clase base mediante la palabra reservada super. La llamada
super(x, y, w, h); inicializa los cuatro miembros dato de la clase
base Ventana: x, y, ancho, alto. A continuación, se inicializa los miembros dato de
la clase derivada, y se realizan las tareas de inicialización que sean necesarias. Si
no se llama explícitamente al constructor de la clase base Java lo realiza por
nosotros, llamando al constructor por defecto si existe.

La función miembro denominada desplazar cambia la posición de la ventana,


añadiéndoles el desplazamiento.

public void desplazar(int dx, int dy){

x+=dx;

y+=dy; }

Redefine la función miembro mostrar para mostrar una ventana con un título.

public void mostrar(){

super.mostrar();

System.out.println("titulo : "+titulo); }
TECNOLÓGICO NACIONAL DE MÉXICO

En la clase derivada se define una función que tiene el mismo nombre y los mismos
parámetros que la de la clase base. Se dice que redefinimos la función mostrar en
la clase derivada. La función miembro mostrar de la clase
derivada VentanaTitulo hace una llamada a la función mostrar de la clase
base Ventana, mediante super.mostrar();

De este modo aprovechamos el código ya escrito, y le añadimos el código que


describe la nueva funcionalidad de la ventana, por ejemplo, que muestre el título.

Si nos olvidamos de poner la palabra reservada super llamando a la


función mostrar, tendríamos una función recursiva. La función mostrar llamaría
a mostrar indefinidamente.

public void mostrar(){ //¡ojo!, función recursiva

System.out.println("titulo : "+titulo);

mostrar(); }

3.2 Clasificación: herencia simple, herencia múltiple

Herencia simple

La herencia simple es la más típica, la que se puede encontrar en cualquier


lenguaje moderno como Java o C#.
La herencia simple es una relación entre una clase padre (clase base) y una
clase hija (clase derivada) llamada "es un tipo de", que muchas veces se
abrevia como isA.
La herencia es simple cuando la clase derivada que estamos considerando
sólo tiene una clase base:
Un ejemplo sería el siguiente:
#include <iostream>
using namespace std;

class Vehiculo {
TECNOLÓGICO NACIONAL DE MÉXICO

public:
void avanza() {}

};
class Coche : public Vehiculo {
public:
void avanza(void)
{ cout << "Avanza coche." << endl; }
};
class Moto: public Vehiculo {
public:
void avanza(void)
{ cout << "Avanza moto." << endl; }
};
int main()
{
Moto t;
Coche c;
t.avanza();
c.avanza();
return 0;
}

Esta es la herencia más útil y típica. Existen otros tipos de herencia marginales en
C++, que se describen a continuación, pero que en la práctica son poco útiles.

Herencia múltiple

En algún momento, un programador puede estar tentado a derivar una clase única
de varias clases. Esto se conoce como "herencia múltiple" y aunque parece útil,
puede provocar problemas, como el importante "problema del diamante". Este
problema ocurre cuando dos clases heredan de la misma clase (como la clase B y
C derivan de la clase A), mientras que otra clase (D) deriva de B y C. Cuando se
TECNOLÓGICO NACIONAL DE MÉXICO

crea un objeto D, el sistema lo trata como un tipo de clase base (clase "Ball" o bola
y "Sphere" o esfera, por ejemplo). En el problema del diamante, el sistema no puede
determinar de forma decisiva qué clase D (¿es tipo A-B-D o tipo A-C-D?) es la que
causa problemas.

Debido a los problemas con la herencia múltiple, Java no la permite. Pero en


realidad las clases derivadas de varias clases base pueden conseguirse de una
forma segura usando "interfaces". Una interfaz es parecida a una clase, pero no
sólo define la estructura de la clase, sino también su código real. Una clase base
que implementa una interfaz no "hereda" necesariamente la funcionalidad de la
interfaz: sólo promete el uso de su estructura. Puesto que una clase que implementa
una interfaz no hereda de otra clase (y no es un tipo de la clase base), un
programador puede implementar varias interfaces usando la misma clase.

Algunos lenguajes orientados a objetos, como C++ permiten herencias múltiples, lo


que significa que una clase puede heredar los atributos de otras dos superclases.
Este método puede utilizarse para agrupar atributos y métodos desde varias clases
dentro de una sola.

3.3 Reutilización de miembros heredados

La reutilización de código se refiere al comportamiento y a las técnicas que


garantizan que una parte o la totalidad de un programa informático existente se
pueda emplear en la construcción de otro programa. De esta forma se aprovecha el
trabajo anterior, se economiza tiempo, y se reduce la redundancia.

La manera más fácil de reutilizar código es copiarlo total o parcialmente desde el


programa antiguo al programa en desarrollo. Pero es trabajoso mantener múltiples
TECNOLÓGICO NACIONAL DE MÉXICO

copias del mismo código, por lo que en general se elimina la redundancia dejando
el código reusable en un único lugar, y llamándolo desde los diferentes programas.
Este proceso se conoce como abstracción. La abstracción puede verse claramente
en las bibliotecas de software, en las que se agrupan varias operaciones comunes
a cierto dominio para facilitar el desarrollo de programas nuevos. Hay bibliotecas
para convertir información entre diferentes formatos conocidos, acceder a
dispositivos de almacenamiento externos, proporcionar una interfaz con otros
programas, manipular información de manera conocida (como números, fechas, o
cadenas de texto).

Para que el código existente se pueda reutilizar, debe definir alguna forma de
comunicación o interfaz. Esto se puede dar por llamadas a una subrutina, a un
objeto, o a una clase.

Construyamos la clase Taxista.java con el siguiente código:


public class Taxista extends Persona {
private int nLicencia;
public void setNLicencia(int num){
nLicencia = num;
}
public int getLicencia(){
return nLicencia;
}
}
Y construyamos ArranqueTaxista.java:
public class ArranqueTaxista {
public static void main (String arg[]){
Taxista tax1 = new Taxista();
tax1.setNombre("Luis");
tax1.setEdad(50);
System.out.println( tax1.getNombre());
TECNOLÓGICO NACIONAL DE MÉXICO

System.out.println(tax1.getEdad());
}
}
Ahora intentemos usar el constructor que existía en la clase Persona que recibia el
nombre de la persona y vamos a usarlo para la clase Taxista. Para ello
construyamos la clase ArranqueTaxista2.java:

public class ArranqueTaxista2 {


public static void main (String arg[]){
Taxista tax1 = new Taxista("Jose");
tax1.setEdad(50);
System.out.println( tax1.getNombre());
System.out.println(tax1.getEdad());
System.out.println(tax1.getNLicencia());
}
}
Se genera un error de compilación, debido a que los constructores no se heredan,
sino que hay que definir nuestros propios constructores. Agreguemos en la clase
Taxista los siguientes constructores:

public Taxista(int licencia){


super();
nLicencia = licencia;
}
public Taxista(String nombre,int licencia){
super(nombre);
nLicencia = licencia;
}
Ahora si podremos compilar y ejecutar la clase ArranqueTaxista2. La llamada al
método super indica que estamos llamando a un constructor de la clase base
TECNOLÓGICO NACIONAL DE MÉXICO

(pensemos que un Taxista antes que Taxista es Persona y por tanto tiene sentido
llamar al constructor de Persona antes que al de Taxista). Además, gracias al
número de parámetros de la llamada a super podemos especificar cuál de los
constructores de la clase base queremos llamar.

En java se pueden emplear dos palabras clave: this y super. Como vimos en la
unidad 1, this hace alusión a todo el objeto y super hace alusión a la parte heredada,
por ello empleamos super para referenciar al constructor de la clase base. Ahora
vamos a agregar la función getNombre dentro de la clase Taxista, es decir, tenemos
la misma función en Persona y en Taxista:

public String getNombre() {


return "Soy un taxista y me llamo: " + super.getNombre();
}
Compilamos Taxista y ejecutamos ArranqueTaxista2. Veremos que el mensaje que
aparece en pantalla demuestra que la función getNombre llamada es la de del tipo
real del objeto construido, en este caso la de la clase derivada que es Taxista.

También apreciamos que para acceder al atributo nombre es necesario acceder al


método getNombre de la clase base (y por ello emplear super).

En java los atributos y métodos de la clase base pueden cambiar su modificador de


visibilidad dentro de la clase derivada, la siguiente tabla recoge dichos cambios:

Modificadores en la clase base:

Public

Private

Protected

Paquete

En la clase derivada se transforman en:

Public
TECNOLÓGICO NACIONAL DE MÉXICO

inaccesible

protected

paquete

Inaccesible significa que, a pesar de haber sido heredado, no hay permisos en la


clase derivada para poder acceder a dicho elemento inaccesible, pero aún así, se
pueden llamar a métodos de la clase base que si pueden acceder y modificar al
elemento.

Recordemos que protected significa que es private, pero que al heredar no se hace
inaccesible, es decir que desde la clase derivada se puede acceder.

3.4 Referencia al objeto de la clase base

La funcionalidad de una clase existente se puede extender al crear una nueva


clase que se deriva de ella. La clase derivada hereda las propiedades de la clase
base y es posible agregar o reemplazar métodos y propiedades según sea
necesario.
En C#, el operador: que equivale a extends e implements en Java, define la
herencia e implementación de interfaces. La clase base siempre debe estar en el
extremo izquierdo en la declaración de clase.
Como Java, C# no admite herencia múltiple, lo que significa que las clases no
pueden heredar más de una clase. Sin embargo, se pueden utilizar interfaces para
ese propósito, de la misma manera que en Java.
El código siguiente define una clase denominada CoOrds con dos variables
miembro privadas x e y que representan la posición del punto. Se tiene acceso a
estas variables mediante propiedades denominadas X e Y, respectivamente:
public class CoOrds
{ private int x, y;
public CoOrds() // constructor
{ x = 0;
y = 0; }
TECNOLÓGICO NACIONAL DE MÉXICO

public int X
{ get { return x; }
set { x = value; }
}
public int Y
{
get { return y; }
set { y = value; }
}
}
Una nueva clase, denominada ColorCoOrds, hereda todos los campos y métodos
de la clase base, a la cual se pueden agregar nuevos campos y métodos para
proporcionar características adicionales en la clase derivada, según sea necesario.
En este ejemplo, se agrega un miembro privado y descriptores de acceso para
agregar color a la clase:
public class ColorCoOrds : CoOrds
{ private System.Drawing.Color screenColor;
public ColorCoOrds() // constructor
{ screenColor = System.Drawing.Color.Red; }
public System.Drawing.Color ScreenColor
{ get { return screenColor; }
set { screenColor = value; }
}
}
El constructor de la clase derivada llama implícitamente al constructor de la clase
base o la superclase, en terminología de Java. En caso de herencia, se llama a
todos los constructores de clase base antes que a los constructores de la clase
derivada en el orden en que las clases aparecen en la jerarquía de clases.
TECNOLÓGICO NACIONAL DE MÉXICO

3.5 Constructores y destructores en clases derivadas

Al instanciar objetos de clases derivadas se inicia una cadena de invocaciones a


constructores en las cuales el constructor de la clase derivada, antes de realizar sus
propias tareas, invoca (ya sea implícita o explícitamente) al constructor de su clase
base. Similarmente, si la clase base fue derivada de otra clase, el constructor de la
clase base debe invocar al constructor de la clase ubicada en el siguiente nivel
superior de la jerarquía, y así sucesivamente. El último constructor invocado en la
cadena es el constructor de la clase Object, cuyo cuerpo se ejecuta primero. El
cuerpo del constructor de la clase derivada se ejecuta al final. El constructor de cada
clase base inicializa las variables de instancia que el objeto de la clase derivada
hereda.
Destructores en clases derivadas
Cuando remueve de la memoria un objeto de una clase derivada, el recolector de
basura invoca al destructor del objeto. Esto inicia una cadena de invocaciones a
destructores, en donde el destructor de la clase derivada y los destructores de las
clases bases directas e indirectas se ejecutan en orden inverso al que se ejecutaron
los constructores, esto es, primero se ejecuta el destructor de la clase derivada y al
final se ejecuta el destructor de la clase base ubicada en el nivel superior de la
jerarquía. La ejecución de los destructores debe liberar todos los recursos que el
objeto adquirió, antes de que el recolector de basura reclame la memoria de ese
objeto. Cuando el recolector de basura invoca al destructor de un objeto de una
clase derivada, ese destructor realiza su tarea y después invoca al destructor de la
clase base. El proceso se repite hasta que se invoca al destructor de la clase Object.
Ejemplo:

// Destruct Derivadas?.cs : Destructores en clases derivadas. using


C = System.Console;
class Animal {
Animal( ) {
C.Write Line?(“Muere mi parte Animal …”);
}}
TECNOLÓGICO NACIONAL DE MÉXICO

class Mamífero : Animal {


Mamífero( ){
C.Write Line(“Muere mi parte Mamífero …”);
}}
class Perro : Mamífero {
Perro( ) {
C.Write Line(“Muere mi parte Perro …”);
}}
public class Principal {
static void Main( ) {
Perro Fido = new Perro ( );
}}

3.6 Redefinición de métodos en clases derivadas

El lenguaje java permite redefinir miembros de la clase base en las clases derivadas,
pero el compilador emite una advertencia cuando detecta una redefinición. Una
advertencia (warning) es un mensaje del compilador acerca de un posible problema.
Sin embargo, en este caso sí se genera código ejecutable (a diferencia del mensaje
de error). Redefinición de campos. El siguiente ejemplo muestra cómo reutilizar los
identificadores de los campos de la clase base en una clase derivada.
Ejemplo de redefinición de las clases derivadas
// Redef.cs : Ejemplifica la redefinición de campos en clases derivadas.
class Punto{
public int x;
public int y;}
class Punto3D : Punto{
public int x ;
public int y ;
public int z ;
}
class Principal{
TECNOLÓGICO NACIONAL DE MÉXICO

public static void Main( ) {


Punto a = new Punto( ); Punto3D b = new Punto3D( );
a.x = 100 ;
a.y = 200 ;
b.x = 300 ;
b.y = 400 ;
b.z = 500 ;
}
}
TECNOLÓGICO NACIONAL DE MÉXICO

Bibliografía

 https://es.ccm.net/contents/411-poo-herencia

 http://www.sc.ehu.es/sbweb/fisica/cursoJava/fundamentos/herencia/herencia.htm

 http://pooitzo.blogspot.com/2012/06/35-constructores-y-destructores-en.html

 http://jbgarcia.webs.uvigo.es/asignaturas/TO/cursilloCpp/15_herencia_simple.html

 https://techlandia.com/herencia-multiple-java-info_269416/

 http://fjglez90.blogspot.com/2012/06/36-redefinicion-de-metodos-en-clases.html

Вам также может понравиться