[英]Java generics - parameterized class vs. typed method
我想這是一個重復的問題,但在瀏覽了大量相關問題之后,我找不到匹配的問題......是的,蹩腳的借口;)
我目前正在為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)?
據我所知,這里沒有理由使用通用方法。 用非泛型方法覆蓋泛型方法可能不會按照您的想法進行。 我在這里和這里討論過這個問題 。 (另請參閱通用方法教程 。)
通用方法的類型由呼叫站點決定。 出於向后兼容性原因,允許將其覆蓋為非泛型。 一個人仍然可以出現並執行以下操作:
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> {…}
這其實很好。
雖然這似乎是一個答案,請隨意添加另一種選擇:
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();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.