hola a todos, tengo la siguiente duda y es con respecto ala utilizacion de <T>
siempre he utilizado es el object y estoy tratando de entender las ventajas de los genericos,
ya se que sirve para asegurarse de tener listas homogéneas y así ahorrase el cast ala salida y ayuda a evitar errores...entre otras cosas...
pero no estoy seguro que mas utilidad tenga, y no tengo muy claro donde es que es util utilizarla .
Una clase para crear y realizar diferentes acciones con arboles que utilizaba Object la cambie a ese tipo generico quedando asi:
/**
Código:
* @version 1.00 2010/4/1
*////arbol binario de busqueda
public abstract class CArbolBB <T>{
// atributos del arbol binario
protected CNodo raiz=null;// raiz del arbol binario
//Nodo de un arbol binario
private class CNodo
{
private T datos;
private CNodo izquierdo;
private CNodo derecho;
public CNodo(){}
}
//Posibles errores que se pueden dar relativos a un nodo
public static final int CORRECTO = 000;
public static final int NO_DATOS = 100;
public static final int YA_EXISTE = 101;
public static final int NO_EXISTE = 102;
public CArbolBB() {}
// metodo para redefinir, comaparando por el atributo que necesitemos
public abstract int comparar(T obj1,T obj2);
//metodo para redifinir, realizar con el nodo visitado
public abstract void procesar(T obj);
//metodo redefinir de tal forma que invoque a inorden con los argumentos deseados
public abstract void visitarInorden();
public T buscar(T obj)
{
// El método buscar permite acceder a un determinado nodo.
CNodo actual = raiz;
int nComp = 0;
// Buscar un nodo que tenga asociados los datos dados por obj
while( actual != null )
{
if(( nComp = comparar( obj, actual.datos ))== 0)
return( actual.datos ); // CORRECTO (nodo encontrado)
else if ( nComp < 0 ) // buscar en el subárbol izquierdo
actual = actual.izquierdo;
else // buscar en el subárbol derecho
actual = actual.derecho;
}
return null; // NO.EXISTE
}
public int insertar(T obj)
{
// El método insertar permite añadir un nodo que aún no está
// en el árbol.
CNodo ultimo = null, actual = raiz;
int nComp = 0;
if( obj == null ) return NO_DATOS;
// Comienza la búsqueda para verificar si ya hay un nodo con
// estos datos en el árbol
while (actual != null)
{
if ((nComp = comparar( obj, actual .datos ))== 0)
break; // se encontró el nodo
else
{
ultimo = actual;
if( nComp < 0 ) // buscar en el subárbol izquierdo
actual = actual.izquierdo;
else // buscar en el subárbol derecho
actual = actual.derecho;
}
}
if ( actual == null ) // no se encontró el nodo, añadirlo
{
CNodo nuevoNodo = new CNodo();
nuevoNodo.datos = obj;
nuevoNodo.izquierdo = nuevoNodo.derecho = null;
// El nodo a añadir pasará a ser la raíz del árbol total si
// éste está vacio, del subárbol izquierdo de "último" si la
// comparación fue menor, o del subárbol derecho de "último" si
// la comparación fue mayor.
if ( ultimo == null ) // árbol vacio
raiz = nuevoNodo;
else if ( nComp < 0 )
ultimo.izquierdo = nuevoNodo;
else
ultimo.derecho = nuevoNodo;
return CORRECTO;
} // fin del bloque if ( actual = null )
else // el nodo ya existe en el árbol
return YA_EXISTE;
}
public T borrar(T obj){
// El método borrar permite eliminar un nodo del árbol.
CNodo ultimo = null, actual = raiz;
CNodo marcado = null, sucesor = null;
int nAnteriorComp = 0, nComp = 0;
if (obj == null) return null; // N0_DAT0S
// Comienza la búsqueda para verificar si hay un nodo con
// estos datos en el árbol.
while( actual != null )
{
nAnteriorComp = nComp; // resultado de la comparación anterior
if (( nComp = comparar( obj, actual.datos )) == 0)
break; // se encontró el nodo
else
{
ultimo = actual ;
if ( nComp < 0 ) // buscar en el subárbol izquierdo
actual = actual.izquierdo;
else // buscar en el subárbol derecho
actual = actual.derecho;
}
} // fin del bloque whlle ( actual !- nuil )
if ( actual != null ){ // se encontró el nodo
marcado = actual ;
if (( actual.izquierdo == null && actual.derecho == null ))
// se trata de un nodo terminal (no tiene descendientes)
sucesor = null;
else if ( actual.izquierdo == null ) // nodo sin subárbol izq.
sucesor = actual.derecho;
else if ( actual.derecho == null ) // nodo sin subárbol derecho
sucesor = actual.izquierdo;
else // nodo con subárbol izquierdo y derecho
{
// Referencia del subárbol derecho del nodo a borrar
sucesor = actual = actual.derecho;
// Descender al nodo más a la izquierda en el subárbol
// derecho de este nodo (el de valor más pequeño) y hacer
// que el subárbol izquierdo del nodo a borrar sea ahora
// el subárbol izquierdo de este nodo.
while ( actual.izquierdo != null )
actual = actual.izquierdo;
actual.izquierdo = marcado.izquierdo;
}
// Eliminar el nodo y rehacer los enlaces
if ( ultimo != null )
{
if( nAnteriorComp < 0 )
ultimo.izquierdo = sucesor;
else
ultimo.derecho = sucesor;
}
else
raiz = sucesor;
return marcado.datos; // CORRECTO
// "marcado" será enviado a la basura
}
else // el nodo buscado no está en el árbol
return null; // NO_EXISTE
}
public void inorden(CNodo r, boolean nodoRaiz)
{
//orden de visita: subarbol izquierdo, raiz y subarbol derecho
CNodo actual = null;
if(nodoRaiz)
actual = raiz;// partir de la raiz
else
actual = r; // partir de un nodo cualquiera
if(actual != null)
{
inorden(actual.izquierdo,false); // visitar subarbol izquierdo
procesar(actual.datos); //procesar los datos del nodo visitado
inorden(actual.derecho, false);//visitar subarbol derecho
}
}
}
si es necesario utilizar genericos aqui?
otra duda me resulto cuando fui a redefinir los metodos abstractos en una subclase y no pude utilizar la misma T asi:
Código:
public abstract class Redefinir_CArbolBB_para_Nota extends CArbolBB{
public int comparar(Object obj1,Object obj2){
if(((objetoNota)(obj1)).ObtenerNota()==((objetoNota)(obj2)).ObtenerNota())
return 0;
else if(((objetoNota)(obj1)).ObtenerNota()<((objetoNota)(obj2)).ObtenerNota())
return -1;
else
return 1;
}
public void procesar(Object obj){
System.out.println("Nombre estudiante "+((objetoNota)(obj)).ObtenerNombre());
System.out.println("Curso estudiante "+((objetoNota)(obj)).ObtenerCurso());
System.out.println("Nota estudiante "+((objetoNota)(obj)).ObtenerNota());
}
//metodo redefinir de tal forma que invoque a inorden con los argumentos deseados
public void visitarInorden(){
inorden(null,true);
}
}
como ven tuve que volver a utilizar Object por que no puedo utilizar genéricos
¿por que no se puede?
y la otra duda fue cuando en la clase principal voy hacer la declaración para que el árbol sea homogéneo asi:
Código:
public class Nota{
public static void main(String arg[]){
Redefinir_CArbolBB_para_Nota<objetoNota> Arbol=new Redefinir_CArbolBB_para_Nota<objetoNota>();
objetoNota obj[]=new objetoNota[6];
for(int i=0;i<6;i++){
System.out.print("Nombre estudiante "+(i+1)+": ");
String N=Leer.leercadena();
System.out.print("Curso estudiante "+(i+1)+": ");
int C=Leer.leerint();
System.out.print("Nota estudiante "+(i+1)+": ");
double NO=Leer.leerint();
obj[i]=new objetoNota(N,NO,C);
Arbol.insertar(obj[i]);
}
Arbol.visitarInorden();
}
}
me marca error en la declaración del objeto: "Redefinir_CArbolBB_para_Nota"
bueno me surgen muchas preguntas:
¿tiene que ver que el objeto sea de la subclase del árbol binario?
¿los genéricos solo sirven para las listas lineales ?
¿o solo funcionan con ciertas clases que vienen con java?
¿si estoy entendiendo bien la utilidad de los genéricos o estoy bien perdido?
Agradezco al que me ayude con estas dudas...