web-dev-qa-db-ja.com

Javaで演算子をオーバーロードすることは可能ですか?

XYサーフェス上の1点を記述する次のクラスがあります。

class Point{
    double x;
    double y;

    public Point(int x, int y){
        this.x = x;
        this.y = y;
    }
}

だから私は+および-演算子は、次のコードを実行する可能性があります。

Point p1 = new Point(1, 2);
Point p2 = new Point(3, 4);
Point resAdd = p1 + p2; // answer (4, 6)
Point resSub = p1 - p2; // answer (-2, -2)

Javaでそれを行うにはどうすればよいですか?または、次のようなメソッドを使用する必要があります。

public Point Add(Point p1, Point p2){
    return new Point(p1.x + p2.x, p1.y + p2.y);
}

前もって感謝します!

20

Javaではこれを行うことはできません。 plusクラスにaddまたはPointメソッドを実装する必要があります。

class Point{
    public double x;
    public double y;

    public Point(int x, int y){
        this.x = x;
        this.y = y;
    }

    public Point add(Point other){
        this.x += other.x;
        this.y += other.y;
        return this;
    }
}

使用法

Point a = new Point(1,1);
Point b = new Point(2,2);
a.add(b);  //=> (3,3)

// because method returns point, you can chain `add` calls
// e.g., a.add(b).add(c)
11
maček

Java Java-ooコンパイラプラグイン を使用してそれを行うことができます。ただし、と書く必要があります。 +演算子のaddメソッド:

public Point add(Point other){
   return new Point(this.x + other.x, this.y + other.y);
}

また、Java-ooプラグインは、これらのメソッド呼び出しに対して演算子を非難します。

7
mart

Javaではオペレーターのオーバーロードはありません。どうやら味の理由のため。本当に残念。

(一部の人々は、Javaが+ with Stringそしておそらくオートボクシング/アンボクシング。)

値の型について話しましょう。

多くの初期のクラス(およびいくつかの後のクラス)は、これを正しく混乱させます。特にAWTで。 AWTでは、場所全体に単純な値のコピーを明示的に作成する必要があります。ほとんどの場合、値型を不変にしたいと思います。クラスはfinalであり、状態を変更しないようにする必要があります(通常、すべてのfinalフィールドが有効な不変を指します)。

そう:

public final class Point {
    private final int x;
    private final int y;

    private Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public static of(int x, int y) {
        return new Point(x, y);
    }

    public int x() {
        return x;
    }
    public int y() {
        return y;
    }
    public Point add(Point other) {
        return of(x+other.x, y+other.y);
    }

    // Standard fluffy bits:
    @Override public int hashCode() {
        return x + 37*y;
    }
    @Override public boolean equals(Object obj) {
        if (!(obj instanceof Point)) {
            return false;
        }
        Point other = (Point)obj;
        return x==other.x && y==other.y;
    }
    @Override public String toString() {
        return "("+x+", "+y+")";
    }
}

元のコードはintdoubleの間で混同されていたので、1つを選択しました。 doubleを使用した場合は、NaNを除外する必要があります。 「ポイント」は絶対ポイントを意味する傾向があり、追加しても意味がありません。 「ベクトル」または「次元」は、目的に応じて、おそらくより適切です。

IDは重要ではないため、コンストラクターは非表示にしています。値がキャッシュされる可能性があります。たとえば、ポイントをゼロポイントに追加することが一般的であるため、ポイントを作成する必要はありません。

たとえば、アキュムレータとして使用するなど、変更可能なバージョンが必要になる場合があります。これは、継承関係のない別のクラスである必要があります。おそらく単純なケースではないでしょうが、とにかくそれを示します:

public final class PointBuilder {
    private int x;
    private int y;

    public PointBuilder() {
    }
    public PointBuilder(Point point) {
        this.x = point.x;
        this.y = point.y;
    }
    public Point toPoint() {
        return new Point(x, y);
    }

    public PointBuilder x(int x) {
        this.x = x;
        return this;
    }
    public PointBuilder y(int y) {
        this.y = y;
        return this;
    }
    public PointBuilder add(Point other) {
        this.x += other.x;
        this.y += other.y;
        return this;
    }
}

Javaで演算子をオーバーロードすることはできません。これはPointクラスで処理する必要があります。

2
Maxim Manco

JavaではJavaでは演算子のオーバーロードがないため、これを行うことはできません。

あなたが言及した2番目のオプションを使用する必要があります:

編集:Pointクラス自体にAddメソッドを追加できます

public Point Add(Point other){
    return new Point(this.x + other.x, this.y + other.y);
}
2
M S