简体   繁体   English

为什么ChangeListener的getSource()不返回用于生成事件的类型的预制对象?

[英]Why doesn't ChangeListener's getSource() return a pre-cast object of the type used to generate an event?

Instead of having to cast the ChangeEvent Object back into a JSpinner Object so that I can access the getValue() method, why doesn't e.getSource() simply return a pre-cast object of the type used to generate the event? 不必将ChangeEvent对象强制转换回JSpinner对象,以便我可以访问getValue()方法,为什么e.getSource()不能简单地返回用于生成事件的类型的预制对象? The first usage of e.getSource() makes it clear that it KNOWS a JSpinner is being used, so why not just cast it back? e.getSource()的首次使用清楚地表明它知道正在使用JSpinner,所以为什么不将其回退呢? It seems like it'd be simpler. 似乎会更简单。 I'm assuming there are safety reasons not to do this, but I'd like to see or hear of a concrete example why that would be a bad thing to have as the default usage. 我假设出于安全原因不这样做,但是我想看看或听到一个具体示例,为什么将其作为默认用法却是一件坏事。

Is it unsafe? 它不安全吗? Is it just bad architecture? 只是糟糕的架构?

public class SpinnerPanel extends JPanel implements ChangeListener {

...

SpinnerPanel()
{
    birthdaySpinner.addChangeListener(this);
    add(birthdaySpinner);
}

@Override
public void stateChanged(ChangeEvent e) 
{
    System.out.println(e.getSource());

    JSpinner spinner = (JSpinner)e.getSource();
    System.out.println(spinner.getValue());
}
}

The fact that the source will be a JSpinner is known at runtime . 源将是JSpinner的事实在运行时是已知 The kind of “automatic type casts” you describe are possible with generics at compile time , but at that time there is no telling where the listener might end up. 您描述的这种“自动类型转换”可能在编译时通过泛型来实现,但那时并没有告诉侦听器可能在哪里结束。 For example, you could take your spinner, obtain a list of all listeners, and then add these listeners to another widget like a check box. 例如,您可以使用微调器,获取所有侦听器的列表,然后将这些侦听器添加到另一个小部件(如复选框)。 There is nothing in your code to tell the compiler at compile time that this won't happen, so there is nothing to tell the compiler that the source will always be a spinner. 您的代码中没有什么可以告诉编译器在编译时不会发生这种情况,因此也没有什么可以告诉编译器源将永远是微调器。

It would theoretically be possible to use generics in some way. 理论上讲,可以某种方式使用泛型。 You could have a ChangeEvent<T> for changes originating from a component of class T . 对于来自类T的组件的更改,您可以具有ChangeEvent<T> You could have a ChangeListener<T> with a method stateChanged(ChangeEvent<? extends T>) . 您可以使用带有状态stateChanged(ChangeEvent<? extends T>)方法stateChanged(ChangeEvent<? extends T>) ChangeListener<T>ChangeListener<T> But then what would be the type for all listeners of a given component of class T ? 但是,对于类T的给定组件的所有侦听器,类型是什么? If it were List<ChangeEvent<T>> then you wouldn't be allowed to add a generic ChangeListener<Object> to that list. 如果它是List<ChangeEvent<T>>则不允许您将通用ChangeListener<Object>到该列表。 So it would have to be List<ChangeEvent<? super T>> 因此它必须是List<ChangeEvent<? super T>> List<ChangeEvent<? super T>> . List<ChangeEvent<? super T>> But if you had such a list in any component, then it would be the same type for all derived components, instead of a more specific type like the generics approach would suggest. 但是,如果您在任何组件中都有这样的列表,那么对于所有派生组件,它将是相同的类型,而不是像泛型方法所建议的那样是更具体的类型。

So on the whole I think this generics approach would make the code a lot harder to write and maintain, would likely leave loopholes in some places, would probably be horrible in terms of backwards compatibility, and on the whole would not be worth the effort. 因此,总的来说,我认为这种泛型方法会使代码更难编写和维护,可能会在某些地方留下漏洞,在向后兼容性方面可能会令人恐惧,并且总体上不值得付出努力。

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

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