web-dev-qa-db-fra.com

Est-il possible de surcharger des opérateurs en Java?

J'ai la classe suivante, qui décrit un point sur XY Surface:

class Point{
    double x;
    double y;

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

Donc je veux surcharger + et - Opérateurs d'avoir Possibilité d'écrire exécuter le code suivant:

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)

Comment puis-je le faire en Java? Ou je devrais utiliser des méthodes comme ceci:

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

Merci d'avance!

20
Dmitry Belaventsev

Vous ne pouvez pas faire cela en Java. Vous devriez mettre en œuvre une méthode plus ou add dans votre classe 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;
    }
}

usage

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

Bien que vous ne puissiez pas le faire dans pure Java Vous pouvez le faire en utilisant Plugin Java-oo compiler . Vous devez écrire Ajouter Méthode pour + opérateur:

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

et Java-Oo Plugin Just Desugar Opérateurs à ces appels de méthode.

7
mart

Il n'y a pas de surcharge de l'opérateur en Java. Apparemment pour des raisons de goût. Pitié vraiment.

(Certaines personnes prétendent que Java a une surcharge, à cause de + avec String et peut-être autoboxying/nonboxing.)

Parlons des types de valeur.

De nombreuses classes précoces (et quelques plus tard) font un gâchis droit de cela. Particulièrement dans l'AWT. Dans AWT, vous devriez expliquer explicitement des copies de valeurs simples partout. Vous voulez presque certainement rendre les types de valeur immuables - la classe devrait être définitive et ne devrait jamais changer d'état (généralement tous les champs final pointant vers des immutables efficaces).

Donc:

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+")";
    }
}

Le code d'origine a été confondu entre int et double, alors j'ai choisi un. Si vous avez utilisé double, vous devez exclure NaN. "Point" a tendance à impliquer un point absolu, ce qui n'a pas de sens à ajouter. "Vecteur" ou "dimension" serait probablement plus approprié, en fonction de ce que vous avez l'intention.

J'ai caché le constructeur, car l'identité n'est pas importante. Éventuellement des valeurs pourraient être mises en cache. Peut-être, disons, communs d'ajouter un point à un point zéro, aucun point n'a besoin d'être créé.

Il est possible que vous souhaitiez peut-être une version mutable, par exemple à utiliser comme accumulateur. Cela devrait être une classe distincte sans une relation d'héritage. Probablement pas dans des cas simples, mais je vais le montrer quand même:

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;
    }
}
3

Vous ne pouvez pas faire cela dans Java car il n'y a pas de surcharge de l'opérateur en Java.

Vous devez utiliser la deuxième option que vous avez mentionnée:

Edit: Vous pouvez ajouter la méthode Add dans la classe de points elle-même

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