首页 > 解决方案 > 如何使用对象的原始类转换引用?

问题描述

我正在开发一个用于处理的 GUI 库,并且我有一个类Component. 我有一堆其他类扩展ComponentLabelButton(扩展LabelPanelIcon。这些类仅包含“逻辑”部分(位置、文本、功能检查是否被单击等)。

这个类Panel里面有一个ArrayListof Component,你可以给它添加按钮、标签等......

为了显示组件,我决定使用一个类Theme,其中包含一些函数的重载display(Component component)(一个用于Label,一个用于Button,一个用于Panel等......)。

在内部display(Panel panel),在某些时候,我会显示面板的所有子项,但是,将它们(子项)视为Buttonor Label,它将所有子项视为Component。我该如何解决这个问题?

1)我已经尝试display()在类Component中使用方法Button等......它部分工作,但它给出了一些“编码问题”:要覆盖函数显示,您必须创建一个新类(例如:GreenBackgroundButton extends Button {})。此外,通过将所有功能放在外部类中,您可以使用单个类控制程序的所有 rapihcs,因此您可以使用单个功能等所有组件具有相同的背景displayBackground()......

2)instanceof不能使用,因为如果我必须使用它来转换面板的子级,用户无法创建自定义组件,因为它们会显示为Component不像TextField(示例)。

3)我试过直接投射display((Button)panel.getChildren.get(0)),但是,因为它显示,当我使用标签时,它会给出一个错误(如预期的那样)。

4)我也尝试过这样的投射:panel.getChildren().get(0).getClass().cast(panel.getChildren().get(0)),但它不起作用,我不知道为什么。(我尝试了它的所有变体,比如创建一个外部对象等......)

5)如果你需要更多的代码,你可以问...

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

我希望在画布上看到面板内的工作按钮,而不是看到组件。我没有任何我现在能想到的特定错误。

标签: javacastingprocessing

解决方案


使用instanceof几乎总是一种 hack,并且可能是糟糕设计的征兆。

您所描述的内容听起来与一个名为Abstract Window Toolkit (AWT) 的现有 Java 库完全一样,因此您可能会考虑“借用”它们的一些设计模式。

  • Component是定义抽象paint()函数的抽象类。该paint()函数接受一个Graphics参数。稍后会详细介绍。
  • ButtonLabel扩展Component和覆盖该paint()功能。
  • Graphics是一个包含 和 之类的函数的drawRect()setBackground()。它封装了共享绘图代码,类似于我认为您的Theme课程会做的事情。

如果我是你,我会考虑为你的图书馆采取类似的方法。

我将尝试解决您的其他一些评论:

示例:GreenBackgroundButton 扩展 Button{}

在这种情况下,优先考虑组合而不是继承。您不需要扩展Button来设置背景。相反,在类(或类)中有一个setBackground()函数。Button()Component

此外,通过将所有函数放在外部类中,您可以使用单个类控制程序的所有 rapihcs,因此您可以使用单个函数 displayBackground() 等为所有组件具有相同的背景。

听起来这属于你的Component班级。

另外,退后一步,我会鼓励您避免过度设计解决方案的诱惑。您可能认为您需要一个具有多个继承级别和许多不同类的复杂设计,但很可能一个更简单的设计可能会为您提供几乎所有您需要的东西。具体来说,我没有看到将任何代码提取到Theme类中的巨大好处。我可能会将所有内容直接放在我的组件子类中,例如Buttonand Label


推荐阅读