简体   繁体   中英

Java generics of generics of

I have a generic class which represents a fragment of text. That fragment of text may have any of a number of different modes (different types of highlighting). Those modes are represented by an Enum. The Enum could be different for each project but it must implement an interface which provides a method to combine 2 of them (could be highlighted and bolded). So i have an interface:

public interface TextFragmentMode<E extends Enum<E>> {
    /**
     * Will combine the supplied mode with the current mode and return the
     * result.
     * 
     * @param mode The mode to combine with.
     * @return The combined mode.
     */
    public E combine( E mode );
}

Then my TextFragment is a container for both a String of text, and a mode. But when I try to declare the class:

public class TextFragment<E extends TextFragmentMode<E extends Enum<E>>> {
    StringBuilder text;
    E mode;
    ...

I get the following error:

Syntax error on token "extends", , expected

Which, according to eclipse syntax highlighting, is referring to the

E extends Enum<E>

portion of the code. Does anyone know what I am doing wrong? I must be missing something about Generics...

--------------------- edit -------------------

I'm finally taking the time to read Effective Java by Josh Bloch (second edition), and it turns out he goes over this use case as Item 34: Emulate extensible enums with interfaces . As much as I would like to say great mind think alike... That would be WAY too presumtuous!

TextFragment<E> needs to say two things about E .

  • It "extends" TextFragmentMode<E> .
  • In order to do that, you must also constrain it to extend Enum<E> .

Because of Java inheritance wonkiness, you need to write that the other way around:

public class TextFragment<E extends Enum<E> & TextFragmentMode<E>> {

The problem is that you're trying to make E extend TextFragmentMode and Enum , which aren't related types. What type E would satisfy both constraints?

I suspect you want two type parameters, something like this:

public class TextFragment<E extends Enum<E>, M extends TextFragmentMode<E>>

Now you have each constraint expressed on a different type parameter, and they both make sense - you can definitely find an E which is an enum, and an M which is a TextFragmentMode<E> . However, it's pretty complicated...

... do you definitely need it to be this generic? What will you be doing with M in the class? Could you not just take a TextFragmentMode<E> as a constructor parameter (or whatever) and make it generic in one type parameter again?

您需要引入一个考虑Enum界限的新类型

public class TextFragment<T extends Enum<T>, E extends TextFragmentMode<T>> {

Without testing, I'd guess:

public class TextFragment<E extends TextFragmentMode<E>> {

Hmm, short test shows it doesn't seem to work either...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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