Java 通用参数扩展 A 或 B

Som*_*Guy 5 java generics

在 Java 中,我们有泛型,并且可以指定泛型参数来扩展/实现某个类/接口。

class MyClass<T extends Number>
Run Code Online (Sandbox Code Playgroud)

还可以指定它必须实现多个接口

class MyClass<T extends Number & Comparable>
Run Code Online (Sandbox Code Playgroud)

我的问题是;如何指定泛型参数必须扩展两个类之一?

Class MyClass<T extends JComponent OR JFrame>
Run Code Online (Sandbox Code Playgroud)

我拥有的是一个Propery类,此时它看起来像这样。

public abstract class Property<T> {

    public abstract void set(JComponent component, T value);
    public abstract void set(JFrame component, T value);
    public abstract T get(JComponent component);
    public abstract T get(JFrame component);

    public static Property<Integer> HEIGHT = new Property<Integer>() {
        @Override
        public void set(JComponent component, Integer value) {
            component.setSize(component.getWidth(), value);
        }

        @Override
        public Integer get(JComponent component) {
            return component.getHeight();
        }

        @Override
        public void set(JFrame component, Integer value) {
            component.setSize(component.getWidth(), value);
        }

        @Override
        public Integer get(JFrame component) {
            return component.getHeight();
        }
    };

    public static Property<Integer> WIDTH = new Property<Integer>() {
        @Override
        public void set(JComponent component, Integer value) {
            component.setSize(value, component.getHeight());
        }

        @Override
        public Integer get(JComponent component) {
            return component.getWidth();
        }

        @Override
        public void set(JFrame component, Integer value) {
            component.setSize(value, component.getHeight());
        }

        @Override
        public Integer get(JFrame component) {
            return component.getWidth();
        }
    };
   ...
}
Run Code Online (Sandbox Code Playgroud)

虽然,更多的属性,如 Background_COLOR 和 LOCATION。

问题真正从这里开始,因为您可能能够为每个属性设置重复代码,但在 Animation 类中情况变得更糟:

public class Animation {

    public static void callbackAnimation(AnimationCallback callback, double duration, double fps) {
        double timeout = (1/fps)*1000;
        int iterations = (int)(duration/timeout);
        for (int i = 0; i <= iterations; i++) {
            callback.run((double)i/(double)iterations);
            try {
                Thread.sleep((long)timeout);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

public static void animateProperty(final JComponent component, final Property<Color> property, Color to, double duration, double fps) {
        final Color currentValue = property.get(component);
        final int differenceRed = to.getRed() - currentValue.getRed();
        final int differenceGreen = to.getGreen() - currentValue.getGreen();
        final int differenceBlue = to.getBlue() - currentValue.getBlue();
        final int differenceAlpha = to.getAlpha() - currentValue.getAlpha();

        Animation.callbackAnimation(new AnimationCallback() {
            @Override
            public void run(double fraction) {
                Color newColor = new Color(
                        (int)(currentValue.getRed()+(differenceRed*fraction)),
                        (int)(currentValue.getGreen()+(differenceGreen*fraction)),
                        (int)(currentValue.getBlue()+(differenceBlue*fraction)),
                        (int)(currentValue.getAlpha()+(differenceAlpha*fraction))
                        );
                property.set(component, newColor);
            }
        }, duration, fps);
    }

    public static void animateProperty(final JFrame component, final Property<Color> property, Color to, double duration, double fps) {
        final Color currentValue = property.get(component);
        final int differenceRed = to.getRed() - currentValue.getRed();
        final int differenceGreen = to.getGreen() - currentValue.getGreen();
        final int differenceBlue = to.getBlue() - currentValue.getBlue();
        final int differenceAlpha = to.getAlpha() - currentValue.getAlpha();

        Animation.callbackAnimation(new AnimationCallback() {
            @Override
            public void run(double fraction) {
                Color newColor = new Color(
                        (int)(currentValue.getRed()+(differenceRed*fraction)),
                        (int)(currentValue.getGreen()+(differenceGreen*fraction)),
                        (int)(currentValue.getBlue()+(differenceBlue*fraction)),
                        (int)(currentValue.getAlpha()+(differenceAlpha*fraction))
                        );
                property.set(component, newColor);
            }
        }, duration, fps);
    }
}
Run Code Online (Sandbox Code Playgroud)

我去掉了一些方法,但你应该得到 idé。我必须为每个方法编写两次,一次用于 JFrame,一次用于 JComponent,这很痛苦。

Uwe*_*ner 5

这不可能; 如果您指定这两个类的公共基类,则只能隐式执行此操作。泛型是为了了解里面的内容而设计的。这并不意味着“一个或另一个”。


mac*_*asz 5

我不认为这是可能的,好吧,拥有这种结构是没有意义的。

当您使用 A & B 指定参数时,您知道您将能够在您拥有的实例上调用 A 和 B 的方法,但是如果您能够指定 A OR B 那么它对编译器是可以调用Aa()还是可以调用Bb();

如果您需要这样的构造,您可能会遇到设计问题,请发布您的代码,我们可能会提供帮助

看到你的代码,也许你应该在 JFrame 和 JComponent 周围使用一个 Adapter 来隐藏重复的代码,虽然 JFrame 和 JComponent 都是Container,你不能使用它吗?