简体   繁体   English

我可以制作一个表现得像原始类型的类吗?

[英]Can i make a class that behave like a primitive type?

I made a Point class to manage xy coordinate (I know some java default packages already have some Point object that behave in a similar way, I use it as a lazy alternative and this is an example, please dont mind it ^^). 我制作了一个Point类来管理xy坐标(我知道一些Java默认软件包已经具有一些以类似方式运行的Point对象,我将其用作惰性选择,这是一个示例,请不要介意^^)。

Before using it I was using the int primitive type. 在使用它之前,我使用了int基本类型。

thing is, when passing a class or a primitive type as parameter of a method, both don't act the same way, if I change the value of a primitive variable in a method, the original variable is unaffected, unlike if I was using an object since its the reference that is passed as parameter. 事实是,当将类或原始类型作为方法的参数传递时,两者的行为方式不同,如果我在方法中更改原始变量的值,则原始变量不会受到影响,这与我使用一个对象,因为它是作为参数传递的引用。

my problem is that since I use Point for math (example below), I have to manually create new object to save the result and I never use it to have a "link" between two variables as I could with how object behave usually. 我的问题是,因为我使用Point进行数学运算(下面的示例),所以我必须手动创建新对象以保存结果,并且我从来不使用它在两个变量之间建立“链接”,就像对象通常的行为一样。

My Point class: 我的积分课程:

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

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

    public Point() {
        this(0, 0);
    }
}

An example of method: 方法示例:

public Point getAdjacent(int x, int y, Direction dir) {
        Point pt = new Point(x, y);//basically, i would like to do that automatically
        switch (dir) {
        case Up:
            pt.y -= 1;
            break;
        case Down:
            pt.y += 1;
            break;
        case Right:
            pt.x -= 1;
            break;
        case Left:
            pt.x += 1;
            break;
        default:
            //do nothing
        }
        return pt;
    }

To summarize, is it possible to make Point behave like a primitive type? 总而言之, 是否可以使Point表现得像原始类型?

EDIT: i mean that it would automatically copy it when passing it as parameter or doing point1=point2 编辑:我的意思是当它作为参数传递或做point1 = point2时,它将自动复制它

First of all: be sure to use break statements in your switch code. 首先:确保在您的切换代码中使用break语句。 Otherwise when case Up is matched, the switch block will "fall through" and will execute: 否则,当大小写匹配时,切换块将“掉线”并执行:

pt.y -= 1; 
pt.y += 1;
pt.x -= 1;
pt.x += 1;

(Reference: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html ) (参考: https : //docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html


According to the question, you can indeed use the Point class. 根据问题,您确实可以使用Point类。 Below code will: 下面的代码将:
1. Use a Point as input. 1.使用一个点作为输入。
2. Extract the variables x and y from the input Point into a copy primitive. 2.从输入Point中将变量x和y提取到复制基元中。
3. Change the copied primitives. 3.更改复制的图元。
4. Create a new Point, based on the copies. 4.根据副本创建一个新的Point。

In this way the "old" Point will be left untouched. 这样,“旧”点将保持不变。

public Point getAdjacent(final Point point, final Direction dir) {
    int x = point.x;
    int y = point.y;
    switch (dir) {
        case Up:
            y -= 1;
            break;
        case Down:
            y += 1;
            break;
        case Right:
            x -= 1;
            break;
        case Left:
            x += 1;
            break;
        default:
            break;
    }
    return new Point(x, y);
}

The question might be a bit too broad, because one could argue quite extensively about what the word "behave" should mean. 这个问题可能有点太广泛了,因为人们可能会对“行为”一词的含义进行广泛的争论。 But to some extent, we can sort this out: 但在某种程度上,我们可以解决此问题:

The shortest answer might be: No, this is not possible. 最简短的答案可能是: 不,这是不可能的。

A slightly more elaborate answer might be: No, it is not yet possible to let a class (or more precisely: an object) behave like a primitive value. 一个更详尽的答案可能是: 不, 尚不可能让一个类(或更准确地说是一个对象)表现得像一个原始值。


The long answer: 长答案:

There are efforts to achieve a behavior that might come close to what you're trying to accomplish. 我们正在努力实现可能与您要实现的目标接近的行为。 The relevant keyword here is Value Types . 此处的相关关键字是“ 值类型”

Some resources: 一些资源:

However, this is not supported in current versions of Java and the JVM, and it might still take a while until the details are sorted out. 但是,当前版本的Java和JVM不支持此功能,并且可能需要一段时间才能整理出详细信息。

Until then, there are some conceivable workarounds to achieve the desired goal. 在此之前,有一些可行的解决方法可以实现预期的目标。

The simplest solution is the one that you already proposed: You always return a new instance instead of modifying a given object. 最简单的解决方案是您已经提出的解决方案:您总是返回一个新实例,而不是修改给定对象。

The example that you showed in the question might not be the best to illustrate this, because the method getAdjacent that you showed could in fact be a static method. 您在问题中显示的示例可能不是最好的例子,因为您显示的方法getAdjacent实际上可能是static方法。 It does not use the instance that it is called on in any way. 它不使用以任何方式调用它的实例。

Then you could always be sure that you received a new instance for each modification. 这样,您始终可以确保每次修改都收到一个新实例。 Otherwise, imagine this code snippet: 否则,请想象以下代码片段:

Point a = new Point(1,2);
Point b = new Point(3,4);

a.add(b);

System.out.println(a); // What does this print?

Depending on the implementation of the add method, the behavior might not be clear. 根据add方法的实现,其行为可能不清楚。 If it was implemented like this: 如果是这样实现的:

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

then the point a would be modified, and the output would be (4,6) . 那么点a将被修改,输出将是(4,6)

But if it was implemented like this 但是如果这样实现

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

then a would remain unaffected, and the output would still be (1,2) . 那么a不会受到影响,并且输出仍然是(1,2)

In general, making something like a Point immutable basically enforces this style of programming. 通常,使Point 不可变之类的东西基本上可以增强这种编程风格。 So you could make the variables x and y in your class final , so that you could always be sure that the object cannot be modified after it was created: 因此,您可以在类中将变量xyfinal ,以便始终确保对象在创建后不能被修改:

public class Point {

    // Note that these are FINAL:   
    private final int x; 
    private final int y;

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

There are some further design considerations for such a seemingly trivial thing like a Point class (some of which I mentioned in this answer ), but discussing them is beyond the scope of this answer. 对于像Point类这样的琐碎事物(还有一些我在此答案中提到的东西),还有一些其他设计上的考虑,但是讨论它们不在此答案的范围之内。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM