4

我想这是一个重复的问题,但是在浏览了大量相关问题之后,我找不到匹配的问题……是的,蹩脚的借口;)

我目前正在为POI HSLF/XSLF实现开发一个通用接口。使用泛型的原因是为了支持Iterable接口,用户代码不需要向下转换到具体的实现,即可以决定是使用实现类还是通用接口。当然,如果没有泛型,返回类型缩小按预期工作。

我的目标是最小化类用户的参数声明 - 请参阅 main 方法。在内部,通用引用可能更复杂。

所以我想要这样的东西:(为了简单起见,我没有使用 Iterable 接口,而是使用了不同的类型参数)

/* 更新:向类添加静态并删除空定义以实际运行示例 */

public class GenericsTest {
    static interface SlideShow {}
    static class HSLFSlideShow implements SlideShow {}

    static interface Notes<SS extends SlideShow> {}
    static class HSLFNotes implements Notes<HSLFSlideShow> {}

    static interface Slide<SS extends SlideShow> {
        <N extends Notes<SS>> N getNotes();
        <N extends Notes<SS>> void setNotes(N n);
    }

    // compile errors
    static class HSLFSlide implements Slide<HSLFSlideShow> {
        HSLFNotes notes = new HSLFNotes();

        @Override
        public HSLFNotes getNotes() { return notes; }
        @Override
        public void setNotes(HSLFNotes n) { notes = n; }
    }

    public static void main(String[] args) {
        HSLFSlide s = new HSLFSlide();
        HSLFNotes n = s.getNotes();
        s.setNotes(n);

        Slide<HSLFSlideShow> s2 = new HSLFSlide();
        Notes<HSLFSlideShow> n2 = s2.getNotes();
    }
}

我可以让它工作......但这似乎有点笨拙:

    static interface Slide<SS extends SlideShow, N extends Notes<SS>> {
        N getNotes();
        void setNotes(N n);
    }

    static class HSLFSlide implements Slide<HSLFSlideShow,HSLFNotes> {
        HSLFNotes notes = new HSLFNotes();

        @Override
        public HSLFNotes getNotes() { return notes; }
        @Override
        public void setNotes(HSLFNotes n) { notes = n; }
    }

    public static void main(String[] args) {
        HSLFSlide s = new HSLFSlide();
        HSLFNotes n = s.getNotes();
        s.setNotes(n);

        Slide<HSLFSlideShow,HSLFNotes> s2 = new HSLFSlide();
        Notes<HSLFSlideShow> n2 = s2.getNotes();
    }

您将如何最小化 main 方法中所需的类型参数(最低为 JDK6)?

4

2 回答 2

3

据我所知,这里没有理由使用泛型方法。用非泛型方法覆盖泛型方法可能不会像您认为的那样做。我在这里这里讨论过这个。(另请参阅通用方法教程。)

泛型方法的类型由调用站点决定。出于向后兼容的原因,允许将其覆盖为非泛型。仍然可以出现并执行以下操作:

HSLFSlide slide = ...;
Slide<HSLFSlideShow> oops = slide;

// perfectly legal
// probably throws a ClassCastException somewhere
oops.<SomeOtherNotes>set(new SomeOtherNotes());

例如,泛型方法让我们定义一个返回其接受的相同类型的方法:

static <T> T pass(T t) { return t; }

String s = pass("abc");
Double d = pass(3.14d);

这就是泛型方法有用的事情。

做你想做的事情的更典型的方法是:

interface Slide<SS extends SlideShow> {
    Notes<SS> getNotes();
    void setNotes(Notes<SS> n);
}

class HSLFSlide implements Slide<HSLFSlideShow> {
    Notes<HSLFSlideShow> notes = new HSLFNotes();

    @Override
    public Notes<HSLFSlideShow> getNotes() { return notes; }
    @Override
    public void setNotes(Notes<HSLFSlideShow> n) { notes = n; }
}

如果有一些要求notes不能是接口的引用类型,你应该再看看你的设计。例如,也许HSLFNotes实现具有应该移动到Notes接口的特性。

另一种方法如下:

interface Slide<N extends Notes<?>> {
    N getNotes();
    void setNotes(N n);
}

class HSLFSlide implements Slide<HSLFNotes> {
    HSLFNotes notes = new HSLFNotes();

    @Override
    public HSLFNotes getNotes() { return notes; }
    @Override
    public void setNotes(HSLFNotes n) { notes = n; }
}

还有来自问题的工作示例:

interface Slide<SS extends SlideShow, N extends Notes<SS>> {…}
class HSLFSlide implements Slide<HSLFSlideShow, HSLFNotes> {…}

这实际上很好。

于 2015-04-04T00:35:37.270 回答
1

尽管这似乎是一个答案,但请随时添加另一种选择:

public class GenericsTest {
    static interface SlideShow {}
    static class HSLFSlideShow implements SlideShow {}

    static interface Notes<SS extends SlideShow> {}
    static class HSLFNotes implements Notes<HSLFSlideShow> {}

    static interface Slide<SS extends SlideShow> {
        <N extends Notes<SS>> N getNotes();
        <N extends Notes<SS>> void setNotes(N n);
    }

    static class HSLFSlide implements Slide<HSLFSlideShow> {
        HSLFNotes notes = new HSLFNotes();

        @SuppressWarnings("unchecked")
        @Override
        public HSLFNotes getNotes() {
            return notes;
        }

        @Override
        public <N extends Notes<HSLFSlideShow>> void setNotes(N n) {
            notes = (HSLFNotes)n;
        }
    }

    public static void main(String[] args) {
        HSLFSlide s = new HSLFSlide();
        HSLFNotes n = s.getNotes();
        s.setNotes(n);

        Slide<HSLFSlideShow> s2 = new HSLFSlide();
        Notes<HSLFSlideShow> n2 = s2.getNotes();
    }
}
于 2015-04-03T22:37:51.353 回答