2009-09-01 9 views
5

私の質問は、行列の操作を扱うクラスを扱っていることに触発されていることを含め、"Writing a generic class to handle built-in types"とはまったく似ています。 その質問はC#を使用して質問されましたが、Generic Operatorsの記事を指していましたが。一般的な方法で数値を扱うにはどうすればいいですか?

私はそれを取得しません。あなたのようなメソッドを持つことができますので、Javaの数は、addメソッドを持っていない:だから

public Number myAdd(Number a, Number b){ 
    return a.add(b); 
} 

どのようにあなたはJavaで数字の複数の種類を扱うことができるようにしたい場合に対応できますか?

答えて

4

基本的な問題は、非常にプリミティブなJavaタイプのシステムです。

Javaに密封された型の概念はないので(JavaではHaskellのような型を推論することもできません)、一般的なNumber + Number - > Number of Trickeryを作る方法はありません。

プリミティブ(およびそれらに自動的にマップできるIntegerなどのオブジェクト)では、プロモーションのタイプと+演算は言語の一部です。 (そして、これは実際の問題の一部です。aとNumber bはaとbが異なる型の場合に何を返すべきですか?)

この動作が本当に必要な場合は、リフレクションまたは一連のチェックとキャストなどを使用する独自のカスタムクラスを見つける(または作成する)必要があります。ジェネリックを使用しても(ジェネリックがタイプ消去されていることに注意してください)、キャスティングを行う必要があります。

私は、これらの問題がNumberがそれほど穏やかである理由の一部であると考えています。

+0

"aとbは異なる型のaと数字のb戻り値はどうすればよいでしょうか"は、問題のほとんどすべてです。 :) –

-1

個人的には、私はBigDecimalsをほとんどすべて使用しています(しかし、主に私が通貨の値を扱うためです)。彼らは任意のサイズのすべての数値を処理します。そのため、私の意見では、これらは汎用的な値であり、Number抽象クラスの代わりに仮説的な例として使用することができます。 すべてをBigDecimalにすることができます。なぜそれを使用しないのですか?

public BigDecimal myAdd(BigDecimal a, BigDecimal b) { 
    return a.add(b); 
} 

EDIT:下記のコメントBigBrothersに対処するため、あなたは常にあなた自身のジェネリックメソッドを作成するのdoubleValue()メソッドを使用することができます。これで唯一の問題は、誰かがBigDecimalの中を通過しているいくつかのまれなケースでは精度を失う可能性があり、それがDouble.maxValue

public Number myAdd(Number a, Number b) { 
    return new BigDecimal(a.doubleValue() + b.doubleValue()); 
} 

A BigDecimalをより大きくなるように、1は、NOのではありません戻っ番号です結果。

+0

あなたが言っていることを見ている間、私はもっとエレガントなものを望んでいました。 –

3

私はそれを得ていません。 Javaの数は はaddメソッドを持っていない...

はどのようにあなたがその署名を定義し、java.lang.Numberadd方法やメソッドを持っていたと仮定?そのセマンティクスをどのように定義しますか?あなたは "混合モード"算術をどのように扱いますか?

これらの質問に回答し、APIを設計することは間違いありませんが、その結果は正しく使用するのが難しい可能性があります。さらに、アプリケーションが「表現に依存しない」算術演算を実行する必要があることは、最も珍しいことです。通常は、算術が実行され、変換が行われる方法を明示的に制御したい/必要とします。すべてのすべてで(Javaのプリミティブ型のプロモーションルールはすでに人々が周りに頭を取得するための十分な困難な!!)

、私はで算術演算をサポートしようとしている日がないによって私たちに良いサービスを行っていると思いますNumber API

3

結果はどれくらいいいですか?

public Number myAdd(Number a, Number b){ 
    return a.doubleValue() + b.doubleValue(); 
} 

しかし、あなたは、たとえば、Javaのプリミティブのプロモーションセマンティクスに一致する何かをしたい場合、あなたはおそらく書き込みする必要があるとしている:答えは「ほとんどが、十分に良い」である場合、これはsufficentする必要がありますあなた自身。 BigDecimal,BigIntegerAtomicDoubleAtomicLong、すべてがorg.apache.commons.lang.mutableなどの「非標準」の実装のすべての組み合わせについてルールが何であるかを理解しなければならないでしょう。 。

これらのほとんどの場合、正しいことが何であるかは不明です。例えば、すべてをBigDecimalに変換することは、引数の1つがApache CommonsのFraction.ONE_THIRDである場合はオプションではありません。また、一般的な方法で変換を行うと、一般的な方法で追加を行うのと同じ問題が発生します。しかし、add()メソッドをNumberに設定すると、すべてのケースを処理するためにすべてのNumber実装が必要になります。それはおそらくそれが存在しない理由です。

0

他の指摘された理由で2つの数字を追加することはできませんが、同じ種類の数字を追加することもできます。結果も同じ種類になります。

interface Arithmetics<T> { 
    T add(T val1, T val2); 
} 

class IntegerArithmetics implements Arithmetics<Integer> { 
    Integer add(Integer val1, Integer val2) { return val1 + val2; } 
} 

//similarly DoubleArithmetics, BigIntegerArithmetics, ... 

Generic Java Mathライブラリがあなたのためにまさにその: あなたはこのようなもので、Javaで一般的な算術演算を作成することができます。

1

ジェネリックaddメソッドを実装する1つの方法は、左手の引数が戻り型を推論させることです。

package mixins; 

import java.math.BigDecimal; 

public class Numbers { 

    public static boolean isZ(Number n) { 
     return n instanceof Integer || n instanceof Long || n instanceof Short || n instanceof Byte; 
    } 

    public static boolean isR(Number n) { 
     return n instanceof Double || n instanceof Float; 
    } 

    public static BigDecimal add(BigDecimal a, Number b) { 
     if (b instanceof BigDecimal) { 
      return a.add((BigDecimal) b); 
     } else if (isZ(b)) { 
      return a.add(new BigDecimal(b.longValue())); 
     } else if (isR(b)) { 
      return a.add(new BigDecimal(b.doubleValue())); 
     } 
     throw new IllegalArgumentException("No valid big decimal translation for " + b.getClass()); 
    } 

    public static Integer add(Integer a, Number b) { 
     return a + b.intValue(); 
    } 

    public static Long add(Long a, Number b) { 
     return a + b.longValue(); 
    } 

    public static Float add(Float a, Number b) { 
     return a + b.floatValue(); 
    } 

    public static Double add(Double a, Number b) { 
     return a + b.doubleValue(); 
    } 
} 

静的メソッドとして実装されている場合は、静的インポートを使用できます。

import static mixins.Numbers.*; 

public class Example { 

    public static void main(String[] args) { 
     BigDecimal fortytwo = new BigDecimal(42); 
     BigDecimal fiftyfive = add(fortytwo, 13); 
     System.out.println(fiftyfive); 
    } 

} 
関連する問題