7 Replies Latest reply: Aug 18, 2011 7:24 AM by Kleopatra RSS

    Generics are killing me ... again ...

    Kleopatra
      My personal enemies hit again: trying something really simple, trigger is an enhancement request in Swingx:

      http://java.net/jira/browse/SWINGX-968

      boils down to allow some kind of grouping (and possibly resorting) of menu items in the ColumnControlButton, should be easily pluggable, no code breaking changes allowed. My go for it is a one-method interface which ... well ... splits a list of Actions into sublists, then the controlButton simply places a separator between the per-list actions.
      // existing api on ColumnControlPopup
      /**
       *  Creates and adds menuItems from the given actions
       */
      void addAdditionalActions(List<? extends Action> actions);
      
      interface Grouper {
          
          /**
           *   splits the given List of Actions into groups
           */
           List<List<????>> group(List<? extends Action> actions)
      }
      what is the correct code for the "????" - it must be of type Actions somehow, but cant make it, experimental permutations of wildcards, Ts, ... they all went wrong at one point or other, except one - which looks ... ehem ... clumsy ...:
         List<List<Action>> group(List<? extends Action> actions);
      Some kind soul please pull me out of that misery

      Thanks
      Jeanette

      [FYI] cross-posted to the swinglabs forum: http://www.java.net/forum/topic/javadesktop/java-desktop-technologies/swinglabs/generics-are-killing-me-again (not really readable there ...)

      Edited by: Kleopatra on Aug 18, 2011 11:24 AM
        • 1. Re: Generics are killing me ... again ...
          800268
          Kleopatra wrote:
          List<List<Action>> group(List<? extends Action> actions);
          // Instead of the unknown type <? extends Action> you want the specific type <A extends Action>.
          <A extends Action> List<List<A>> group(List<A> actions);
          Edited by: Walter Laan , forum swallows <.A (without the dot)
          • 2. Re: Generics are killing me ... again ...
            EJP
            Exactly. @OP what you need to understand is that every occurrence of ? in a generic declaration refers to something different. If you want them to refer to the same thing, name them with a letter.
            • 3. Re: Generics are killing me ... again ...
              Kleopatra
              Walter, EJP,

              ookay, I can implement such a method - good to know what's the right-thingy :-) and can use it insided a foreach loop.
              // interface method that implements the grouping
              public <A extends Action> List<List<A>> groupItDamned(List<A> actions);
                      
              // method that wants to get the grouped list
              public void addAdditionalAction(List<? extends Action> actions) {
                   for (List<? extends Action> group : grouper.groupItDamned(actions)) {
                        addItems(group);
                        addSeparator();
                   }
              }
              What I still don't get is how to assign it to a List-of-Lists of which type:
              // method that wants to get the grouped list
              public void addAdditionalAction(List<? extends Action> actions) {
                   List<List<????>> groups = grouper.groupItDamned(actions);
                   for (List<????> group : groups) {
                        addItems(group);
                        if (group == groups.get(groups.size() - 1))
                            addSeparator();
                   }
              }
              (could change the logic to avoid that, but feel like I'm shortly before a little victory against the enemy, so pushing as long as I have your attention :-)

              Edit: ahhh ... power of posting, maybe?
              List<? extends List<? extends Action>> groups = grouper.groupItDamned(actions);
              for (List<? extends Action> group : groups) {
                  ....
              }
              Thanks
              Jeanette

              Edited by: Kleopatra on Aug 18, 2011 1:40 PM
              • 4. Re: Generics are killing me ... again ...
                EJP
                Same again. Change the ? to a letter and reuse it everywhere it applies
                public <T extends Action> void addAdditionalAction(List<T> actions) {
                It seems to me that you may want to make <T extends Action> a parameter of the class instead of a parameter of all these methods.
                • 5. Re: Generics are killing me ... again ...
                  Kleopatra
                  Hmm ... can't change the signature (of addAdditionalActions), maybe should have to start with, but now it's too late. The intention at that time was to allow whatever Action types in the parameter list, didn't really care (and couldn't make it compile without the ?, so took the seemingly shortest way out ;-)

                  Thanks
                  Jeanette
                  • 6. Re: Generics are killing me ... again ...
                    EJP
                    You probably can change it, because it is probably binary-compatible. It is certainly seems source-compatible to me. I would try it. In any case as the method clearly isn't working yet I don't see why you can't change it. And indeed you may not have any choice about that.
                    • 7. Re: Generics are killing me ... again ...
                      Kleopatra
                      Hmm ... doesn't compile. But maybe I'm misunderstanding you, so trying to clarify:
                      // existing framework code
                      
                      interface ColumnControlPopup {
                         void addAdditionalActions(List<? extends Action> actions);
                      }
                      
                      // existing implementation 
                      
                      class DefaultColumnControlPopup {
                         @Override
                         public void addAdditionalActions(List <? extends Action> action) {
                            ...
                         }
                      }
                      
                      // your suggestion to change the interface signature of the popup
                      
                      <A extends Action> void addAdditionalActions(List<A> actions);
                      with the change the default implementation doesn't compile, errors either

                      "The method addAdditionalActionItems(List<? extends Action>) of type ColumnControlButton.DefaultColumnControlPopup must override or implement a supertype method"

                      or (after removing the override annotation)
                      "Name clash: The method addAdditionalActionItems(List<? extends Action>) of type ColumnControlButton.DefaultColumnControlPopup has the same erasure as addAdditionalActionItems(List<A>) of type ColumnControlPopup but does not override it"

                      similarly, all existing implementations would blow?

                      Thanks
                      Jeanette