0

I'm trying to write a generic widget that takes a (any) enumset and pops up a simple form to allow the the individual enums to be turned on and off. Below is a minimal version of the class (actually set up to run on android), but eclipse is moaning that "The method add(Capture#-7 of ?) in the type AbstractCollection is not applicable for the arguments(T)".

A few lines earlier I have invoked remove (which has exactly the same signature) with no problems. Trying to turn the enum into a set first doesn't help either.

What is the magic syntax I need to fix this?

I may well not be using the best class definition either ;) I'm using the Android Developer Tools v21.1.0-569685, but the problem also shows up on Eclipse proper (Indigo)

package com.test.ui;

import java.util.EnumSet;

import android.util.Log;
import android.view.View;
import android.view.LayoutInflater;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.CheckBox;

public class EnumSetSelector<T extends Enum<?>> implements OnClickListener{

  Class<T> enumclass;
  EnumSet<?> theset; // EnumSet<T> theset; fails
  boolean haschanged;

  public EnumSetSelector(Class<T> eclass) {
    enumclass = eclass;
  }

  public ViewGroup prepareSet(EnumSet<?> esvals, ViewGroup vg, LayoutInflater li) {
    theset = esvals;
    T[] allvals = enumclass.getEnumConstants();
    Log.d("XXXXXXZ","here are " + allvals.length);
    ViewGroup grp = (ViewGroup)li.inflate(R.layout.ui_enum_selector,vg,false);
    for (T av:allvals) {
      Log.d("XXXXXXZ"," - " + av);
      CheckBox cb = (CheckBox)li.inflate(R.layout.ui_enum_selector_entry,vg,false);
      cb.setText(String.valueOf(av));
      cb.setChecked(theset.contains(av));
      cb.setTag(av);
      grp.addView(cb);
      esvals.remove(av);
    }
    vg.addView(grp);
    return grp;
  }

  @Override
  public void onClick(View v) {
    final T thisenum = (T)v.getTag();
    final boolean oldval = theset.contains(thisenum);
    final CheckBox cb = (CheckBox)v;
    if (cb.isChecked() != oldval) {
      if (cb.isChecked()) {
        cb.setChecked(false);
        theset.remove(thisenum);
      } else {
        cb.setChecked(true);
        theset.add(thisenum);
        theset.add(EnumSet.of(thisenum));
      }
      Log.d("XXXXXXZ", "" + String.valueOf(v.getTag()) + " now "
        + (theset.contains(thisenum)));
    }
  }
}
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
pootle
  • 507
  • 6
  • 15
  • 2
    You can't add anything to an EnumSet>, except null, since you don't know the type of the set. What happens when you make the set an `EnumSet`, and the class an `EnumSetSelector>`? – JB Nizet Mar 24 '13 at 16:21
  • "`EnumSet theSet;` fails": Please be more specific: Fails to compile? If so, what's the compilation error? – meriton Mar 24 '13 at 16:46
  • Ooh yes JB - that works if I use T EnumSet everywhere, it's fine - I thought I'd tried that before, but I've also upgraded eclipse in the meantime... Sometimes going round in circles for too long make me dizzy! Meriton - it's in the first paragraph – pootle Mar 24 '13 at 18:04

1 Answers1

0

Echoing JB Nizet's comment, you should declare your class as:

EnumSetSelector<T extends Enum<T>>

In other words, with the same recursive bounds that Enum and EnumSet declare.

Then make sure to type theset and esvals as EnumSet<T> instead of EnumSet<?>.

Paul Bellora
  • 54,340
  • 18
  • 130
  • 181