简体   繁体   English

如何使用对象的原始 class 投射引用?

[英]How to cast a reference with an object's original class?

I'm working on a GUI library for Processing, and I have got a class Component .我正在开发一个用于处理的 GUI 库,并且我有一个 class Component I have a bunch of other classes that extend Component : Label , Button (Which extends Label ), Panel and Icon .我有一堆其他类扩展ComponentLabelButton (扩展Label ), PanelIcon These classes continue just the "logic" part (position, text, function checking if they are clicked etc...).这些类仅继续“逻辑”部分(位置、文本、function 检查它们是否被单击等......)。

The class Panel has inside of it an ArrayList of Component , and you can add to it buttons, labels etc... class Panel内部有一个ArrayListComponent ,您可以添加按钮、标签等...

To display the components I decided to use a class Theme , which has inside some overloadings of the function display(Component component) (one for Label , one for Button , one for Panel etc...).为了显示组件,我决定使用 class Theme ,其中包含Button display(Component component)的一些重载(一个用于Label等...,一个用于Panel )。

Inside display(Panel panel) , at some point, I display all the children of the panel, but, instead of treating them (the children) as Button or Label , it treats all of them as Component .display(Panel panel)内部,有时,我会显示面板的所有子项,但是,不是将它们(子项)视为ButtonLabel ,而是将它们全部视为Component How can I solve this ISSUE?我该如何解决这个问题?

  1. I've already tried to use a method display() inside the classes Component , Button etc... it works partly, but it gives some "coding problems": to override the function display you have to create a new class (Example: GreenBackgroundButton extends Button{}).我已经尝试在ComponentButton等类中使用方法display() ......它部分工作,但它给出了一些“编码问题”:要覆盖 function 显示,您必须创建一个新的 class (例如: GreenBackgroundButton 扩展了 Button{})。 Also, by putting all the function in an external class, you can control all the grapihcs of you Program with a single class, so you can have the same background for all the components with a single function displayBackground() etc... Also, by putting all the function in an external class, you can control all the grapihcs of you Program with a single class, so you can have the same background for all the components with a single function displayBackground() etc...

  2. instanceof can't be used, because, if I have to use it to cast the children of the panel, the user can't create custom components, because they would be displayed as Component not as TextField (example).不能使用instanceof ,因为如果我必须使用它来投射面板的子项,则用户无法创建自定义组件,因为它们将显示为Component而不是TextField (示例)。

  3. I've tried casting directly display((Button)panel.getChildren.get(0)) , but, as it Should, when I use a label, it gives an error (as expected).我已经尝试直接投射display((Button)panel.getChildren.get(0)) ,但是,当我使用 label 时,它会给出错误(如预期的那样)。

  4. I've tried casting like this too: panel.getChildren().get(0).getClass().cast(panel.getChildren().get(0)) , and it doesn't work, I don't know why.我也尝试过这样的投射: panel.getChildren().get(0).getClass().cast(panel.getChildren().get(0)) ,它不起作用,我不知道为什么。 (I tried all its variants, like creating an external object etc...) (我尝试了它的所有变体,比如创建一个外部 object 等......)

  5. If you need more code, you can ask...如果您需要更多代码,您可以询问...

public void display(Panel panel) {
    println("panel");
    if (panel.isVisible()) {
      pushMatrix();
      translate(panel.getX(), panel.getY());
      displayBackground(panel, #AAAAAA);

      for (int i = 0; i < panel.getChildren().size(); i++) {
        this.display(panel.getChildren().get(i).getClass().cast(panel.getChildren().get(i))); //THIS IS THE LINE WITH THE ISSUE
        //println(panel.getChildren().get(i).getClass().cast(panel.getChildren().get(i)));
      }
      popMatrix();
    }
  }


Theme basicTheme;
Button close;
Panel panel;

void settings() {
  size(400, 600, P2D);
}

void setup() {
  basicTheme = new Theme();

  close = new Button();
  close.setBounds(10, 10, 100, 25);
  close.setText("close");

  panel = new Panel();
  panel.setBounds(50, 200, 200, 200);
  panel.add(close);
}

void draw() {
  background(255);

  basicTheme.display(panel);
}

I expect to see on the canvas a working button inside the panel, instead of seeing a component.我希望在 canvas 上看到面板内的一个工作按钮,而不是看到一个组件。 I don't have any particular error I can think of right now.我现在没有想到任何特别的错误。

Using instanceof is almost always a hack, and is probably a symptom of a bad design.使用instanceof几乎总是一种 hack,并且可能是糟糕设计的征兆。

What you've described sounds exactly like an existing Java library called the Abstract Window Toolkit (AWT), so you might consider "borrowing" some of their design patterns.您所描述的内容听起来与现有的 Java 库完全一样,称为Abstract Window 工具包(AWT),因此您可能会考虑“借用”他们的一些设计模式。

  • Component is an abstract class that defines an abstract paint() function. Component是一个抽象的 class,它定义了一个抽象的paint() function。 The paint() function takes a Graphics argument. paint() function 采用Graphics参数。 More on that in a second.稍后会详细介绍。
  • Button and Label extend Component and overide the paint() function. ButtonLabel扩展Component并覆盖paint() function。
  • Graphics is a class that contains functions like drawRect() and setBackground() . Graphics是一个 class ,其中包含drawRect()setBackground()等函数。 It encapsulates shared drawing code, similar to what I think your Theme class would do.它封装了共享绘图代码,类似于我认为您的Theme class 会做的事情。

If I were you, I would consider taking a similar approach for your library.如果我是你,我会考虑为你的图书馆采取类似的方法。

I'll try to address some of your other comments:我将尝试解决您的其他一些评论:

Example: GreenBackgroundButton extends Button{}示例:GreenBackgroundButton 扩展 Button{}

Favor composition over inheritance for cases like this.对于这种情况,优先考虑 inheritance 的组合 You should not need to extend Button to set a background.您不需要扩展Button来设置背景。 Instead, have a setBackground() function in the Button() class (or in the Component class).相反,在Button() class (或在Component类)中有一个setBackground() function。

Also, by putting all the function in an external class, you can control all the rapihcs of you Program with a single class, so you can have the same background for all the components with a single function displayBackground() etc. Also, by putting all the function in an external class, you can control all the rapihcs of you Program with a single class, so you can have the same background for all the components with a single function displayBackground() etc.

It sounds like this belongs in your Component class.听起来这属于您的Component class。

Also, taking a step back, I would encourage you to avoid the temptation to over-engineer a solution.另外,退后一步,我会鼓励您避免过度设计解决方案的诱惑。 You might think you need a complicated design with several levels of inheritance and many different classes, but chances are a simpler design will probably get you almost everything you need.您可能认为您需要一个复杂的设计,其中包含多个级别的 inheritance 和许多不同的类,但很可能一个更简单的设计可能会为您提供几乎所有您需要的东西。 Specifically, I don't see a huge benefit to extracting any code into the Theme class.具体来说,我认为将任何代码提取到Theme class 中没有巨大的好处。 I would probably put everything directly in my component subclasses like Button and Label .我可能会将所有内容直接放在我的组件子类中,例如ButtonLabel

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

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