Results 1 to 13 of 13
  1. #1
    Shayke is offline Member
    Join Date
    Jan 2011
    Posts
    5
    Rep Power
    0

    Default Using generics with interfaces

    I would like to be able to declare a class with a generic parameter that is guaranteed to implement a specific interface. If I could do it the way I wanted, the code would look like this:
    Java Code:
         class MyClass<E implements MyInterface> { ... }
    As suspected, the compiler doesn't accept the syntax, though it seems to me that it could work conceptually. Is there some reason having to do with type erasure that this couldn't compile to a valid runtime object?

    Or more to the point, is there some other way to do this? I've thought of using an adapter class like this:
    Java Code:
         class MyClass<E extends MyAdapter> {...}
    But the problem is the interface i have in mind (Shape) is already defined in Java, and I want to be able to use existing implementations of it. If I interpose my own adapter class I won't have access to them in this parametrization.

    Any workarounds? It would be a big boon to my program to be have a way to do this.

  2. #2
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    I think that this:

    Java Code:
    class MyClass<E implements MyInterface> { ... }

    should be this:


    Java Code:
    class MyClass<E extends MyInterface> { ... }

    for example,

    Java Code:
    import java.util.ArrayList;
    import java.util.List;
    
    public class InterfaceFooTest {
       public static void main(String[] args) {
          String[] data = {"Fe", "Fi", "Fo", "Fum"};
          GenericUseOfInterface<Derived> genericUOI = new GenericUseOfInterface<Derived>();
          for (String datum : data) {
             genericUOI.add(new Derived(datum));
          }
          
          genericUOI.doAll();
       }
    }
    
    class Derived implements MyInterface {
       private String text;
       
       Derived(String text) {
          this.text = text;
       }
       
       public void myMethod() {
          System.out.println("Text: " + text);
       }
       
    }
    
    
    class GenericUseOfInterface <E extends MyInterface> {
       List<E> myList = new ArrayList<E>();
       
       public void add(E e) {
          myList.add(e);
       }
       
       public void doAll() {
          for (E e : myList) {
             e.myMethod();
          }
       }
    }
    
    interface MyInterface {
       void myMethod(); 
    }
    Last edited by Fubarable; 02-08-2011 at 03:17 AM. Reason: posted an example

  3. #3
    Shayke is offline Member
    Join Date
    Jan 2011
    Posts
    5
    Rep Power
    0

    Default

    Quote Originally Posted by Fubarable View Post
    I think that this:

    Java Code:
    class MyClass<E implements MyInterface> { ... }

    should be this:


    Java Code:
    class MyClass<E extends MyInterface> { ... }

    Unfortunately that would defeat the purpose of using interfaces. For example, if my interface is Shape, then I would want to be able to use the class Rectangle as my parameter. But Rectangle does not extend Shape, it only implements it.

  4. #4
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Quote Originally Posted by Shayke View Post
    Unfortunately that would defeat the purpose of using interfaces. For example, if my interface is Shape, then I would want to be able to use the class Rectangle as my parameter. But Rectangle does not extend Shape, it only implements it.
    I think you don't understand what I'm saying. Even though Rectangle2D implements Shape, this will work. You can't implement an interface within a generic statement, you can only extend. Please test it with the way I describe and look at my example above. You'll then see your logical error.
    Last edited by Fubarable; 02-08-2011 at 03:41 AM.

  5. #5
    Shayke is offline Member
    Join Date
    Jan 2011
    Posts
    5
    Rep Power
    0

    Default

    Excellent! Many thanks for taking the time to demonstrate with the example. (I don't remember seeing the example in your original reply- did you add it there afterwards? Sorry if I just plain missed it in the first go-round.)
    Last edited by Shayke; 02-08-2011 at 03:41 AM.

  6. #6
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

  7. #7
    toadaly is offline Senior Member
    Join Date
    Jan 2009
    Posts
    671
    Rep Power
    6

    Default

    Fubarable is correct. When using generics in this fashion, you always use 'extends' even for interfaces. The following compiles and runs, doing what you would expect.

    Java Code:
    public class junk<E extends stuff> {
    
        public static void main(String[] args) throws Exception {
    
    
    	new junk<stuffDoer>(new stuffDoer());
    
        }
    
        public junk(E theStuffDoer) {
            theStuffDoer.doStuff();
        }
    
    }
    
    interface stuff {
        public void doStuff();
    }
    
    class stuffDoer implements stuff {
        public void doStuff(){
    	System.out.println("I did stuff");
        }
    }

  8. #8
    Shayke is offline Member
    Join Date
    Jan 2011
    Posts
    5
    Rep Power
    0

    Default Part 2

    I see these examples work, but I'm stuck again trying to understand the general case. This is more a theoretical question at this point.

    Suppose I want a generic parameter that is required to both extend a class in the usual sense and also implement an interface. So the code might look like:

    Java Code:
         class MyClass<E extends BaseClass, BaseInterface> {...}

    (That actually compiles but does not perform as desired- the compiler appears to regard MyClass as having two separate variables, one extending BaseClass, the other extending BaseInterface).

    Is there any way to put both conditions on a single parameter? Once again, I can't work around the problem by making my own class to extend the parameter from, since in the most general case there might be an existing class I want to use that already extends BaseClass and implements BaseInterface.

    Off the top of my head it's hard to come up with a really compelling example- maybe it's critical that I know all my parametrized classes implement Serializable in addition to extending a base class?

    In any case, since it seems like it should be possible to do this, I'd like to know how or understand why it can't be done.

  9. #9
    toadaly is offline Senior Member
    Join Date
    Jan 2009
    Posts
    671
    Rep Power
    6

    Default

    Ok, I understand what' you're trying to do. Hopefully it makes sense why

    Java Code:
    class MyClass<E extends BaseClass implements InterfaceA, InterfaceB>
    Is exactly accomplished simply by

    Java Code:
    class MyClass<E extends BaseClass>
    You *can* specify multiple interface generics, and the proer syntax is

    Java Code:
    class MyClass<E extends InterfaceA & InterfaceB>
    The following compiles and runs and does what you expect:

    Java Code:
    public class junk<E extends stuff & morestuff> {
    
        public static void main(String[] args) throws Exception {
    
    
    	new junk<stuffDoer>(new stuffDoer());
    
        }
    
        public junk(E theStuffDoer) {
            theStuffDoer.doStuff();
        }
    
    }
    
    interface morestuff {
      public void doMoreStuff();
    }
    
    interface stuff {
        public void doStuff();
    }
    
    class stuffDoer implements stuff, morestuff {
    
      public void doMoreStuff(){}
    
        public void doStuff(){
    	System.out.println("I did stuff");
        }
    }

  10. #10
    JosAH's Avatar
    JosAH is online now Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,371
    Blog Entries
    7
    Rep Power
    20

    Default

    Quote Originally Posted by Fubarable View Post
    You can't implement an interface within a generic statement, you can only extend.
    Most likely I don't understand your remark, but e.g. think about Comparable<T>. That's a generic interface and it needs to be implemented, not extended.

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  11. #11
    Shayke_ is offline Member
    Join Date
    Feb 2011
    Posts
    4
    Rep Power
    0

    Default

    Quote Originally Posted by toadaly View Post
    You *can* specify multiple interface generics, and the proer syntax is

    Java Code:
    class MyClass<E extends InterfaceA & InterfaceB>

    Thanks. The specific example I had in mind was more like:

    Java Code:
    class MyClass<E extends BaseClass & InterfaceA & InterfaceB> {...}

    But I've verified that this works as well.

    Not that it matters, but it seems odd to have invented a new syntax for generics, when intuitively (to me anyway) the old syntax would have sufficed. What else could the following mean except what I wanted?

    Java Code:
    class MyClass<E extends BaseClass implements InterfaceA, InterfaceB> {...}

    (BTW, I am the original poster, but messed up my password & email on the original account. Long story... Just wanted to say thanks for the solution.)

  12. #12
    j2me64's Avatar
    j2me64 is offline Senior Member
    Join Date
    Sep 2009
    Location
    Zurich, Switzerland
    Posts
    962
    Rep Power
    5

    Default

    Quote Originally Posted by toadaly View Post
    Fubarable is correct. When using generics in this fashion, you always use 'extends' even for interfaces.

    sure. when using generics the idea of extends is: accept all types that extends that class OR implements that interface(s).
    Last edited by j2me64; 02-08-2011 at 10:31 PM.

  13. #13
    j2me64's Avatar
    j2me64 is offline Senior Member
    Join Date
    Sep 2009
    Location
    Zurich, Switzerland
    Posts
    962
    Rep Power
    5

    Default

    Quote Originally Posted by JosAH View Post
    Most likely I don't understand your remark, but e.g. think about Comparable<T>. That's a generic interface and it needs to be implemented, not extended.

    kind regards,

    Jos

    you are talking about something else. fubarable wrote about "within a generic statement" so <E implements Y> is not valid. here is a snapshot from my sun certified java programmer (c) study guide

    Last edited by j2me64; 02-08-2011 at 10:46 PM.

Similar Threads

  1. Interfaces
    By computerquip in forum New To Java
    Replies: 19
    Last Post: 09-08-2009, 04:58 PM
  2. Interfaces
    By jon80 in forum New To Java
    Replies: 2
    Last Post: 05-03-2008, 09:57 PM
  3. interfaces..
    By sireesha in forum New To Java
    Replies: 5
    Last Post: 01-16-2008, 05:52 PM
  4. Interfaces
    By Kavana Krishnappa in forum New To Java
    Replies: 7
    Last Post: 12-11-2007, 04:28 PM
  5. Interfaces
    By imran_khan in forum New To Java
    Replies: 5
    Last Post: 07-30-2007, 08:11 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •