Generics and Polymorphism

Discussion in 'Java' started by Jason Cavett, Apr 28, 2008.

  1. Jason Cavett

    Jason Cavett Guest

    I'm having some issues with generics and polymorphism. I thought this
    was possible in Java - maybe someone can clear up what I'm doing
    wrong. Basically, when I actually try to use the preference, the code
    will not compile and I get the following error. How can I do what I'm
    trying to do?

    Here is the code that has the error:

    PreferencesEnum.DERIVED_PREFERENCE.getPreference().setValue(new
    String());

    The error is:
    The method setValue(capture#2-of ? extends Object) in the type
    Preference<capture#2-of ? extends Object> is not applicable for the
    arguments (String)


    Thanks,
    Jason

    --- CLASS LISTINGS ---

    I have an enum:

    PreferencesEnum {
    DERIVED_PREFERENCE(new DerivedPreference());

    private final Preference<? extends Object> pref;

    private PreferencesEnum(Preference<? extends Object> pref) {
    this.pref = pref;
    }

    public Preference<? extends Object> getPreference() {
    return pref;
    }
    }

    And I have the generic Preference:
    public abstract class Preference<E extends Object> {

    // provides access to the preferences per application, per user
    protected static Preferences prefs =
    Preferences.userNodeForPackage(Main.class);

    /**
    * Default constructor.
    */
    public Preference() {
    }

    /**
    * Perform a refresh when the preferences change.
    */
    public abstract void refresh();

    /**
    * Set the value of the preference.
    *
    * @param value
    * the value to set
    */
    public abstract void setValue(E value);

    /**
    * Get the value of the preference.
    *
    * @return the associated preference value
    */
    public abstract E getValue();
    }

    And here's a derived preference:

    public class DerivedPreference extends Preference<String> {

    private static final String KEY = "derived";

    private static final String DEFAULT = "DEFAULT VALUE";

    /**
    * Default constructor
    */
    public DerivedPreference() {
    super();
    }

    @Override
    public String getValue() {
    return prefs.get(DerivedPreference.KEY,
    DerivedPreference.DEFAULT);
    }

    @Override
    public void refresh() {
    }

    @Override
    public void setValue(String value) {
    prefs.put(DerivedPreference.KEY, value);
    }
    }
    Jason Cavett, Apr 28, 2008
    #1
    1. Advertising

  2. Jason Cavett

    Daniel Pitts Guest

    Jason Cavett wrote:
    > I'm having some issues with generics and polymorphism. I thought this
    > was possible in Java - maybe someone can clear up what I'm doing
    > wrong. Basically, when I actually try to use the preference, the code
    > will not compile and I get the following error. How can I do what I'm
    > trying to do?
    >
    > Here is the code that has the error:
    >
    > PreferencesEnum.DERIVED_PREFERENCE.getPreference().setValue(new
    > String());
    >
    > The error is:
    > The method setValue(capture#2-of ? extends Object) in the type
    > Preference<capture#2-of ? extends Object> is not applicable for the
    > arguments (String)
    >
    >
    > Thanks,
    > Jason
    >
    > --- CLASS LISTINGS ---
    >
    > I have an enum:
    >
    > PreferencesEnum {
    > DERIVED_PREFERENCE(new DerivedPreference());
    >
    > private final Preference<? extends Object> pref;
    >
    > private PreferencesEnum(Preference<? extends Object> pref) {
    > this.pref = pref;
    > }
    >
    > public Preference<? extends Object> getPreference() {
    > return pref;
    > }
    > }
    >

    The problem is that DERIVED_PREFERENCE.getPreference() returns
    Preference<? extends Object>, who's setValue() method accepts only E,
    which can't be statically determined from the context...


    Another issue is that enums can't have type parameters, so that makes
    what you're trying to do specifically impossible using "enum"......


    What you *can* do is instead of "enum", use a plain old class.

    class PreferencesEnum<E> {
    private final Preference<E> pref;

    public static final DERIVED_PREFERENCE = new
    PreferencesEnum<String>(new DerivedPreference());

    private PreferenceEnum(Preference<E> pref) {
    this.pref = pref;
    }
    }

    etc...

    Hope this helps.
    Daniel Pitts, Apr 29, 2008
    #2
    1. Advertising

  3. Jason Cavett

    Jason Cavett Guest

    On Apr 28, 8:14 pm, Daniel Pitts
    <> wrote:
    > Jason Cavett wrote:
    > > I'm having some issues with generics and polymorphism.  I thought this
    > > was possible in Java - maybe someone can clear up what I'm doing
    > > wrong.  Basically, when I actually try to use the preference, the code
    > > will not compile and I get the following error.  How can I do what I'm
    > > trying to do?

    >
    > > Here is the code that has the error:

    >
    > > PreferencesEnum.DERIVED_PREFERENCE.getPreference().setValue(new
    > > String());

    >
    > > The error is:
    > > The method setValue(capture#2-of ? extends Object) in the type
    > > Preference<capture#2-of ? extends Object> is not applicable for the
    > > arguments (String)

    >
    > > Thanks,
    > > Jason

    >
    > > --- CLASS LISTINGS ---

    >
    > > I have an enum:

    >
    > > PreferencesEnum {
    > >   DERIVED_PREFERENCE(new DerivedPreference());

    >
    > >   private final Preference<? extends Object> pref;

    >
    > >   private PreferencesEnum(Preference<? extends Object> pref) {
    > >    this.pref = pref;
    > >   }

    >
    > >   public Preference<? extends Object> getPreference() {
    > >    return pref;
    > >   }
    > > }

    >
    > The problem is that DERIVED_PREFERENCE.getPreference() returns
    > Preference<? extends Object>, who's setValue() method accepts only E,
    > which can't be statically determined from the context...
    >
    > Another issue is that enums can't have type parameters, so that makes
    > what you're trying to do specifically impossible using "enum"......
    >
    > What you *can* do is instead of "enum", use a plain old class.
    >
    > class PreferencesEnum<E> {
    >     private final Preference<E> pref;
    >
    >     public static final DERIVED_PREFERENCE = new
    > PreferencesEnum<String>(new DerivedPreference());
    >
    >     private PreferenceEnum(Preference<E> pref) {
    >       this.pref = pref;
    >     }
    >
    > }
    >
    > etc...
    >
    > Hope this helps.


    Alright. It did help and I appreciate it.

    The solution does seem a little clunky, however. Not being able to
    paramaterize enums is kind of painful. Is there another possible way
    of handling preferences that I'm not seeing? Basically, I want to
    avoid having a huge file that contains every individual preference
    (which is what was in place originally). Trying to edit that file was
    a nightmare.

    Either way, this solution works. Thanks again, Daniel.
    Jason Cavett, Apr 29, 2008
    #3
  4. Jason Cavett

    Daniel Pitts Guest

    Jason Cavett wrote:
    > On Apr 28, 8:14 pm, Daniel Pitts
    > <> wrote:
    >> Jason Cavett wrote:
    >>> I'm having some issues with generics and polymorphism. I thought this
    >>> was possible in Java - maybe someone can clear up what I'm doing
    >>> wrong. Basically, when I actually try to use the preference, the code
    >>> will not compile and I get the following error. How can I do what I'm
    >>> trying to do?
    >>> Here is the code that has the error:
    >>> PreferencesEnum.DERIVED_PREFERENCE.getPreference().setValue(new
    >>> String());
    >>> The error is:
    >>> The method setValue(capture#2-of ? extends Object) in the type
    >>> Preference<capture#2-of ? extends Object> is not applicable for the
    >>> arguments (String)
    >>> Thanks,
    >>> Jason
    >>> --- CLASS LISTINGS ---
    >>> I have an enum:
    >>> PreferencesEnum {
    >>> DERIVED_PREFERENCE(new DerivedPreference());
    >>> private final Preference<? extends Object> pref;
    >>> private PreferencesEnum(Preference<? extends Object> pref) {
    >>> this.pref = pref;
    >>> }
    >>> public Preference<? extends Object> getPreference() {
    >>> return pref;
    >>> }
    >>> }

    >> The problem is that DERIVED_PREFERENCE.getPreference() returns
    >> Preference<? extends Object>, who's setValue() method accepts only E,
    >> which can't be statically determined from the context...
    >>
    >> Another issue is that enums can't have type parameters, so that makes
    >> what you're trying to do specifically impossible using "enum"......
    >>
    >> What you *can* do is instead of "enum", use a plain old class.
    >>
    >> class PreferencesEnum<E> {
    >> private final Preference<E> pref;
    >>
    >> public static final DERIVED_PREFERENCE = new
    >> PreferencesEnum<String>(new DerivedPreference());
    >>
    >> private PreferenceEnum(Preference<E> pref) {
    >> this.pref = pref;
    >> }
    >>
    >> }
    >>
    >> etc...
    >>
    >> Hope this helps.

    >
    > Alright. It did help and I appreciate it.
    >
    > The solution does seem a little clunky, however. Not being able to
    > paramaterize enums is kind of painful. Is there another possible way
    > of handling preferences that I'm not seeing? Basically, I want to
    > avoid having a huge file that contains every individual preference
    > (which is what was in place originally). Trying to edit that file was
    > a nightmare.
    >
    > Either way, this solution works. Thanks again, Daniel.

    Are they truly preferences, or are they configuration? If its actually
    configuration, you could try using Properties and/or a XML Spring container.

    Alternatively, you can have a less generic Preferences class that has
    fields and getters/setters for each preference that can be set.

    The third approach is to use a EnumMap<PreferenceType, Object>, but you
    don't get the type safety.

    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
    Daniel Pitts, Apr 29, 2008
    #4
  5. Jason Cavett

    Jason Cavett Guest

    On Apr 29, 3:52 pm, Daniel Pitts
    <> wrote:
    > Jason Cavett wrote:
    > > On Apr 28, 8:14 pm, Daniel Pitts
    > > <> wrote:
    > >> Jason Cavett wrote:
    > >>> I'm having some issues with generics and polymorphism.  I thought this
    > >>> was possible in Java - maybe someone can clear up what I'm doing
    > >>> wrong.  Basically, when I actually try to use the preference, the code
    > >>> will not compile and I get the following error.  How can I do what I'm
    > >>> trying to do?
    > >>> Here is the code that has the error:
    > >>> PreferencesEnum.DERIVED_PREFERENCE.getPreference().setValue(new
    > >>> String());
    > >>> The error is:
    > >>> The method setValue(capture#2-of ? extends Object) in the type
    > >>> Preference<capture#2-of ? extends Object> is not applicable for the
    > >>> arguments (String)
    > >>> Thanks,
    > >>> Jason
    > >>> --- CLASS LISTINGS ---
    > >>> I have an enum:
    > >>> PreferencesEnum {
    > >>>   DERIVED_PREFERENCE(new DerivedPreference());
    > >>>   private final Preference<? extends Object> pref;
    > >>>   private PreferencesEnum(Preference<? extends Object> pref) {
    > >>>    this.pref = pref;
    > >>>   }
    > >>>   public Preference<? extends Object> getPreference() {
    > >>>    return pref;
    > >>>   }
    > >>> }
    > >> The problem is that DERIVED_PREFERENCE.getPreference() returns
    > >> Preference<? extends Object>, who's setValue() method accepts only E,
    > >> which can't be statically determined from the context...

    >
    > >> Another issue is that enums can't have type parameters, so that makes
    > >> what you're trying to do specifically impossible using "enum"......

    >
    > >> What you *can* do is instead of "enum", use a plain old class.

    >
    > >> class PreferencesEnum<E> {
    > >>     private final Preference<E> pref;

    >
    > >>     public static final DERIVED_PREFERENCE = new
    > >> PreferencesEnum<String>(new DerivedPreference());

    >
    > >>     private PreferenceEnum(Preference<E> pref) {
    > >>       this.pref = pref;
    > >>     }

    >
    > >> }

    >
    > >> etc...

    >
    > >> Hope this helps.

    >
    > > Alright.  It did help and I appreciate it.

    >
    > > The solution does seem a little clunky, however.  Not being able to
    > > paramaterize enums is kind of painful.  Is there another possible way
    > > of handling preferences that I'm not seeing?  Basically, I want to
    > > avoid having a huge file that contains every individual preference
    > > (which is what was in place originally).  Trying to edit that file was
    > > a nightmare.

    >
    > > Either way, this solution works.  Thanks again, Daniel.

    >
    > Are they truly preferences, or are they configuration?  If its actually
    > configuration, you could try using Properties and/or a XML Spring container.
    >
    > Alternatively, you can have a less generic Preferences class that has
    > fields and getters/setters for each preference that can be set.
    >
    > The third approach is to use a EnumMap<PreferenceType, Object>, but you
    > don't get the type safety.
    >
    > --
    > Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>


    I'm not sure what you mean by preferences vs. configuration.
    (However, intuitively, I would say that these are preferences.)

    When you say, "you can have less generic Preferences class..." do you
    mean, I don't program to a generic interface and, instead, each
    preference object has a similar naming scheme, but each knows exactly
    what it has to set and get?

    class Preference1 {
    void set(String blah) ...
    String get() ...
    }

    class Preference2 {
    void set(Boolean blah) ...
    Boolean get() ...
    }


    Something along those lines?

    Thanks again for your help.
    Jason Cavett, May 1, 2008
    #5
  6. Jason Cavett

    Daniel Pitts Guest

    Jason Cavett wrote:
    > On Apr 29, 3:52 pm, Daniel Pitts
    > <> wrote:
    >> Alternatively, you can have a less generic Preferences class that has
    >> fields and getters/setters for each preference that can be set.

    >
    > I'm not sure what you mean by preferences vs. configuration.
    > (However, intuitively, I would say that these are preferences.)
    >
    > When you say, "you can have less generic Preferences class..." do you
    > mean, I don't program to a generic interface and, instead, each
    > preference object has a similar naming scheme, but each knows exactly
    > what it has to set and get?
    >
    > class Preference1 {
    > void set(String blah) ...
    > String get() ...
    > }
    >
    > class Preference2 {
    > void set(Boolean blah) ...
    > Boolean get() ...
    > }
    >
    >
    > Something along those lines?
    >
    > Thanks again for your help.


    Actually, I was more along the lines of:

    public class Preferences implements Serializable {
    private static final long serialVersionUID = 1;
    private Color favoriteColor;
    private String explitive;
    private boolean coldSoup;
    public enum Animal {
    cat, dog, bird, fish;
    }
    private Animal pet;


    public Color getFavoriteColor() {
    return favoriteColor;
    }

    public void setFavoriteColor(Color favoriteColor) {
    this.favoriteColor = favoriteColor;
    }

    public String getExplitive() {
    return explitive;
    }

    public void setExplitive(String explitive) {
    this.explitive = explitive;
    }

    public boolean isColdSoup() {
    return coldSoup;
    }

    public void setColdSoup(boolean coldSoup) {
    this.coldSoup = coldSoup;
    }

    public Animal getPet() {
    return pet;
    }

    public void setPet(Animal pet) {
    this.pet = pet;
    }
    }

    so, if you can use
    preferences.setExplitive("Dag-nabbit!");
    preferences.setColdSoup(false); // like my soups hot.
    preferences.setPet(Preferences.Animal.cat); //
    preferences.setFavoriteColor(Color.purple);


    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
    Daniel Pitts, May 1, 2008
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    1
    Views:
    10,411
    kj12345
    Mar 1, 2005
  2. Juergen Berchtel
    Replies:
    1
    Views:
    5,968
    John C. Bollinger
    May 20, 2005
  3. Krivenok Dmitry
    Replies:
    13
    Views:
    1,386
    Axter
    Jun 1, 2006
  4. Daniel Pitts
    Replies:
    19
    Views:
    508
    Daniel Pitts
    Sep 30, 2007
  5. Soul
    Replies:
    0
    Views:
    503
Loading...

Share This Page