我正在用 Java 编写一个程序(处理 4)。
处理在后台隐藏了一些东西,这使得事情变得更加复杂。主程序“GeometryView”继承自PApplet类,具有通常的功能。 (这是在Processing中创建项目时创建的第一个选项卡)
ArrayList<Datum> datums = new ArrayList<Datum>();
void setup(){
size(1400, 900);
surface.setResizable(true);
//fullScreen();
frameRate(120);
datums.add(new Datum(0,0));
datums.add(new Datum(1,2));
datums.add(new Datum(3,4));
}
void draw() {
background(30);
stroke(220);
if(Functions.convex(datums.get(0),datums.get(1),datums.get(2))){
println("These points are part of a convex corner of geometry");
}
}
我有一个类,用于保存名为“Datum”的 X 和 Y 值。这是处理中的一个单独选项卡。
class Datum {
float x;
float y;
Datum(float x, float y){
this.x = x;
this.y = y;
}
void drawDatum(int size){
//print("X = " + this.x + ", Y = " + this.y);
ellipse(this.x, -this.y, size, size);
}
Datum clone(){
return new Datum(x,y);
}
}
在单独的“函数”选项卡下,我有一个静态类,用于保存不同的函数。这是为了简化程序的主要部分,因为我可以调用这些函数而无需实例化该类。 (这可能不是执行此操作的正确方法,但它现在有效。我只需调用“Functions.funcName();”这也可能是我的问题所在的线索)
static class Functions{
//...
//other functions
//...
static float crossproduct(Datum a, Datum b) {
return a.x * b.y - a.y * b.x;
}
static boolean convex(Datum a, Datum b, Datum c) {
Datum ab = new Datum(b.x - a.x, b.y - a.y); // Error here on "new Datum(x,y)"
Datum bc = new Datum(c.x - b.x, c.y - b.y);
return crossproduct(ab, bc) > 0;
}
}
上线
Datum ab = new Datum(b.x - a.x, b.y - a.y);
我收到一条错误消息
“无法访问 GeometryView 类型的封闭实例。必须使用 GeometryView 类型的封闭实例来限定分配。” (GeometryView是主类和项目的名称)。
我读了一些其他文章,提到将 Datum 类设为静态,但随后我无法访问像 ellipse() 这样的内置处理函数,并且收到此错误。
“无法从 PApplet 类型对非静态方法 ellipse(float, float, float, float) 进行静态引用”
void drawDatum(int size){
//print("X = " + this.x + ", Y = " + this.y);
ellipse(this.x, -this.y, size, size); // <---- Error is here
}
另一个解决方案是创建主类的另一个实例来访问 Datum 类。也许这会起作用,但仅仅为了访问一个简单的类而再次实例化整个程序似乎可能是一个性能问题。
如何在 Functions 类中使用 Datum 类而不破坏程序的其他部分?我可以使用哪些术语来更多地了解我正在尝试做的事情?
您可以调用
expressionOfTypeGeometryView.new Datum()
来消除该错误,但会提出一个新问题:如何获得 that。好吧,Datum 实例有这样的引用 - 非静态内部类有一个其外部类型的秘密隐藏字段(这里有一个外部类型,但处理也是隐藏的 - 这里有很多巫术魔法,其中不幸的是,这让这有点复杂)。
不过,为了让代码读起来不那么糟糕,我建议采用这种替代方法。添加到您的 Datum 类:
public Datum newDatum(int x, int y) {
return new Datum(x, y);
}
这确实有效,因为 Datum 确实具有隐藏字段 - 因此它可以使新的 Datum 对象“开箱即用”,而不需要奇怪的
expr.new Datum
语法。这意味着您需要 Datum 的实例来创建新的 Datum 对象 - 但您确实有一个实例。
或者,如果需要更好的 API,请尝试:
public Datum subtract(Datum other) {
return new Datum(x - other.x, y - other.y);
}
并将代码中的
Datum ab = new Datum(b.x - a.x, b.y - a.y);
替换为 Datum ab = b.subtract(a);
,这让我觉得总体上更具可读性 - 代码现在可以更好地描述意图。