class Algoritmos {                                    // mismo estilo que java.Mathm que es una clase y está llena de funciones estáticas 
   static <T extends Comparable> T min(T a, T b) {    // se necesita prometer que T implementa java.lang.Comparable (que es una interfaz, pero aquí se debe usar extends) 
      if (a.compareTo(b) <= 0) {                      // sin esa promesa, el lenguaje **no permitirá** llamar a .compareTo aún si el tipo T usado lo provee 
         return a; 
      } else {                                        // a.compareTo(b) devuelve un valor negativo si a es menor que b, 0 si son iguales, y un valor positivo si a es mayor que b 
         return b; 
      } 
   } 
} 
 
class EjemploBien implements Comparable<EjemploBien> {      // prometemos implementar Comparable 
   int v; 
 
   @Override 
   public int compareTo(EjemploBien otro) { 
      if (v < otro.v) { 
         return -1; 
      } else if (v > otro.v) { 
         return +1; 
      } else { 
         return 0; 
      } 
   } 
} 
 
class EjemploMal {                                          // lo mismo pero sin decir que implementamos Comparable 
   int v; 
 
   public int compareTo(EjemploBien otro) { 
      if (v < otro.v) { 
         return -1; 
      } else if (v > otro.v) { 
         return +1; 
      } else { 
         return 0; 
      } 
   } 
} 
 
void main( ) { 
   var a = new EjemploBien( ); 
   var b = new EjemploBien( );      // no se puede declarar varios var en la misma línea XD 
   a.v = 1; 
   b.v = 2; 
   var c = Algoritmos.min(a, b); 
 
   var x = new EjemploMal( ); 
   var y = new EjemploMal( ); 
   x.v = 1; 
   y.v = 2; 
   var z = Algoritmos.min(x, y);    // error aquí: EjemploMal no promete implementar Comparable
} 
