Number non dovrebbe avere un metodo add() .
Dichiarare un metodo in una classe base (o in un'interfaccia, se è per questo), è una promessa per implementare questo metodo. Se la tua classe base ha add(Integer i) , è una promessa che ogni istanza di Number - sia un Float o un Integer - avrà quel metodo.
Puoi usare i generici, come commentato da jozefg - ma poi le tue due classi non condividono una superclasse comune : Integer extends Number<Integer> e Float extends Number<Float> . Queste sono due classi diverse, che condividono il loro codice. In fase di esecuzione (in Java), la cancellazione lo fa apparire come se fosse della stessa classe, ma questo è un aspetto tecnico; Quando si tratta di termini statici (in fase di compilazione), le due classi sono distinte.
Un'altra soluzione dinamica è di avere Number definire add(Number) , o entrambi add(Integer) e add(Float) , e lanciare un'eccezione quando viene invocato il metodo sbagliato; Questo non è certamente quello che cerchi, e generalmente non è considerato un buon uso delle funzionalità orientate agli oggetti.