Puis-je effectuer des opérations arithmétiques sur la classe de base Number?

J’essaie de créer une classe générique en Java qui effectuera des opérations sur les nombres. Dans l’exemple suivant, addition, comme suit:

public class Example  { public T add(T a, T b){ return a + b; } } 

Pardonnez ma naïveté car je suis relativement nouveau sur Java Generics. Ce code ne parvient pas à se comstackr avec l’erreur:

L’opérateur + n’est pas défini pour le ou les types d’argument T, T

Je pensais qu’avec l’ajout de “extend Number”, le code serait compilé. Est-il possible de faire cette Java ou devrais-je créer des méthodes surchargées pour chaque type de numéro?

Le numéro n’a pas d’opérateur + associé, et il ne peut pas non plus y avoir de surcharge de l’opérateur.

Ce serait bien quand même.

En gros, vous demandez à Java d’autoboxer un descedant de Number qui inclut par exemple Integer, Float et Double, qui pourrait être auto-substitué et auquel un opérateur plus serait appliqué, toutefois, il pourrait exister un nombre quelconque d’autres descendants inconnus de Number qui ne pourraient pas l’être. , et cela ne peut pas être connu avant l’exécution. (Damas effacement)

Votre problème n’est pas vraiment lié aux génériques, mais plutôt aux opérateurs, aux primitives ou aux objects, et à la mise en boîte automatique.

Penses-y:

 public static void main(Ssortingng[] args) { Number a = new Integer(2); Number b = new Integer(3); Number c = a + b; } 

Ce qui précède ne comstack pas

 public static void main(Ssortingng[] args) { Integer a = new Integer(2); Integer b = new Integer(3); Number c = a + b; } 

La compilation ci dessus est compilée, mais uniquement à cause de l’autoboxing – qui est une sorte de colle de syntaxe hacky introduite dans Java 5, et ne fonctionne (à la compilation) qu’avec certains types concrets: int-Integer par exemple.

En arrière-plan, le compilateur Java est en train de réécrire la dernière instruction (“Je dois désencapsuler a et b pour appliquer l’opérateur de sum avec des types de données primitifs, et encadrer le résultat pour l’affecter à l’object c “) ainsi:

  Number c = Integer.valueOf( a.intValue() + b.intValue() ); 

Java ne peut pas décompresser un Number car il ne connaît pas le type concret lors de la compilation et ne peut donc pas deviner son équivalent primitif.

Vous pouvez faire quelque chose comme ça

  class Example  { public Number add(T a, T b){ return new Double(a.doubleValue() + b.doubleValue()); } } 

Oui, Nathan a raison. Si vous voulez quelque chose comme ça, vous devez l’écrire vous-même

 public class Example  { private final Calculator calc; public Example(Calculator calc) { this.calc = calc; } public T add(T a, T b){ return calc.add(a,b); } } public interface Calculator { public T add(T a, T b); } public class IntCalc implements Calculator { public final static IntCalc INSTANCE = new IntCalc(); private IntCalc(){} public Integer add(Integer a, Integer b) { return a + b; } } ... Example ex = new Example(IntCalc.INSTANCE); System.out.println(ex.add(12,13)); 

Dommage que Java n’ait pas de classes de type (Haskell) ou d’objects implicites (Scala), cette tâche serait un cas d’utilisation parfait …

Il y a des questions similaires à celle-ci, et la réponse est que vous ne pouvez pas le faire comme ça.

Vous pouvez vérifier si a et b sont une instance de Long / Double / Integer / etc. et déléguer l’ajout à des méthodes comme:

 public Integer add(Integer a, Integer b) { return a+b; // this actually uses auto boxing and unboxing to int } 

Et vous devez en créer un pour chaque type qui étend le numéro, ce qui n’est pas vraiment faisable. En d’autres termes, n’utilisez pas de génériques pour les opérations numériques. Le nombre en tant que superclasse est assez limité.

Considérez l’ Example , comment + travaillerait-il? Il n’y a pas d’ add ou de nombre similaire, ni même d’ Integer .

Pire encore, considérez que la final class FunkyNumber extends Number { ... weird stuff, no add op ... } .

Même la bibliothèque d’exécution Java a ce problème, la plupart des méthodes traitant des primitives doivent dupliquer la même fonctionnalité.

L’option la plus rapide serait d’écrire votre code pour un type, puis de le copier et de remplacer le type pour générer les méthodes pour les autres types. Un court script devrait suffire à cela.