如何在静态类中实例化对象,而无需在处理 [duplicate] 中创建主类的实例

How can I instantiate an object within a static class without creating an instance of the main class in Processing [duplicate]

提问人:Andrew Cline 提问时间:11/18/2023 最后编辑:Andrew Cline 更新时间:11/18/2023 访问量:71

问:

我正在用 Java 编写一个程序(处理 4)。

处理在后台隐藏了一些东西,这使得这更加复杂。主程序“GeometryView”扩展了 PApplet 类并具有常用功能。(这是在“处理”中创建项目时创建的第一个选项卡)

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 类中使用“new Datum(x,y)”?创建对主类的引用可能会导致内存问题,还是只是创建引用?

Java 嵌套 处理 实例化

评论

0赞 Mark Rotteveel 11/18/2023
请提供一个与您提出的问题一致的最小可重现示例。静态类只能嵌套在其他类中,但您显示的类不会嵌套在另一个类中。此外,您显示的错误和您提到的代码调用了一个方法,但您显示的任何代码都没有定义该方法。Functionsellipse
0赞 Mark Rotteveel 11/18/2023
另外,标题与您的问题有什么关系?
0赞 Andrew Cline 11/18/2023
ellipse 方法是 Processings API 的一部分。我相信 Processing 中的每个类都在 PApplet 类中,但我无法找到有关此的明确信息。标题也不知何故搞砸了。这不是我回顾问题时的标题
1赞 user85421 11/18/2023
类必须是 ;该方法移动(并改编)到其他地方,例如主程序 - 否则,函数必须接收一个附加参数:a 或类似参数可以创建一个 ||多想一想,为什么不把功能本身设在自己身上呢?(有点不一致,但在其他地方进行其他操作)DatumstaticdrawDatumSupplierDatumDatumdrawDatum
1赞 user85421 11/18/2023
但我仍然希望在自己身上声明类似......我也不喜欢像了解主程序这样的数据类;也许更改 draw 方法来接收实例(就像使用 Java Swing 一样)||((而且我不会推送大多数关于编程的视频教程))crossProductDatumDatumGeometryView

答:

2赞 rzwitserloot 11/18/2023 #1

你可以打电话来消除这个错误,但会打开一个新问题:你如何得到。好吧,Datum 实例有这样一个引用 - 非静态内部类有一个其外部类型的秘密隐藏字段(这里有一个外部类型,但处理也是隐藏的 - 这里发生了很多巫毒魔法,不幸的是,这有点复杂)。expressionOfTypeGeometryView.new Datum()

不过,为了最终得到的代码读起来不是一场彻底的灾难,我建议采用这种替代方法。添加到 Datum 类:

public Datum newDatum(int x, int y) {
  return new Datum(x, y);
}

这确实有效,因为 Datum 确实有隐藏字段 - 因此它可以“开箱即用”地制作新的 Datum 对象,而不需要奇怪的语法。这意味着您需要一个 Datum 实例来创建新的 Datum 对象 - 但您确实有一个实例。expr.new 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);

评论

0赞 Andrew Cline 11/18/2023
完美的答案!我还有一个问题。我的代码的另一部分需要类似的东西。我使用以下命令创建了一个引用:这是在内存中创建我的程序的副本还是只是对它的引用?GeometryView gv = new GeometryView();
1赞 rzwitserloot 11/18/2023
您不想要视图。,顾名思义,总是创建一个新的引用。这不是一个完整的副本,(只是一个包含字段值的内存块,你不用它来复制代码,那毫无意义,想想看)但是,仍然不是你想要的(它得到一个所有字段的新版本)。 只是不是答案。每个非静态类都有一个 GV 引用(将在变量中为您提供该引用,然后您可以传递该变量)。newGeometryView gv = new GeometryView()GeometryView gv = GeometryView.this;