Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (522)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (590)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Generics and wildcards  (Read 1831 times)
0 Members and 1 Guest are viewing this topic.
Offline swpalmer

JGO Coder


Exp: 12 years


Where's the Kaboom?


« Posted 2005-11-17 20:53:04 »

Trying to wrap my head around this... hope it isn't an Eclipse bug.. that would be irritating...

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
interface A
{
   void doStuff();
}

class B
{
  Set<? extends A> doers;

  public B()
  {
   doers = new HashSet<A>();  // do I have to use the wild card here too?  It doesn't complain about the assignment.
  }

  void addA(A a)
  {
   // Eclipse complains about this: "The method add(capture-of ? extends A) in the type Set<capture-of ? extends A> is not applicable for the arguments (A)
   doers.add(a);
  }

  void removeA(A a)
  {
    // But no complaint here!!
    doers.remove(a);
  }

   void doStuff()
   {
      // and no complaint here
      for(A a : doers)
      {
        a.doStuff();
      }
   }
}

Offline Ask_Hjorth_Larsen

Junior Devvie




Java games rock!


« Reply #1 - Posted 2005-11-17 21:15:20 »

So your set is declared as something containing only a specific subclass of A.

First you assign it specifically as a set of A with new HashSet<A>. You can't use the wildcard here, because the type (HashSet<A>) must be determined by object creation. (I think it would not compile if you use a wildcard)

Next, you try to add an object of type A. This is dangerous because what if "?" actually denotes the subclass B of A? Then it isn't legal to store any A in the set, ONLY those who are actually B. We wouldn't know unless the set is actually declared as Set<A>. Thus, you would get rid of the warning by declaring your set as Set<A> instead of Set<? extends A>.

Now, why does the remove method not complain? That's because the remove method of Set takes an Object as an argument, not a generic T. From this method signature we can see that the question "does my Set<A> contain this String, and if it does please remove it?" is considered harmless, which makes sense since the answer is just "no" in the worst case. However, adding a String would certainly be dangerous.

Last, since any element Set<? extends A> is automatically an instance of A, it is safe to call doStuff() on that element.

(EDIT: minor stuff)
Offline swpalmer

JGO Coder


Exp: 12 years


Where's the Kaboom?


« Reply #2 - Posted 2005-11-17 22:08:05 »

So your set is declared as something containing only a specific subclass of A.

This is where I always get confused.  I thought Set<? extends A> specifically indicated that it was NOT a specific subclass of A, but rather anything that extended A.
Then I try to work out how Set<A> and Set<? extends A> differ... my brain starts to go soft...

In any case...
Quote
First you assign it specifically as a set of A with new HashSet<A>.

Ok, so the Set<? extends A>, though not declared as such, is now specifically a Set<A>.  The assignment works, so everything is still legit.

Quote
Next, you try to add an object of type A. This is dangerous because what if "?" actually denotes the subclass B of A? Then it isn't legal to store any A in the set, ONLY those who are actually B. We wouldn't know unless the set is actually declared as Set<A>. Thus, you would get rid of the warning by declaring your set as Set<A> instead of Set<? extends A>.

Ah-ha.. yes... I see the distinction.

Now the thing is, I don't think I can declare my add method as add(<? extends A> a)  because it STILL wouldn't know if 'a' was some OTHER class that extends A.  Right?

So I suppose I should never have declared the Set using the wildcard at all.  All I care about is that the set is hold some form of A objects.  Every time I look at <? extends A> I think it means precisely that.. I don't care what the object is, so long as it is an A.  But the wildcard simply isn't useful in this context.  I still struggle every time I try to figure out when I SHOULD use the <? extends X> form instead of just <X> .
(We will leave<? super A> for another day... it's even scarier Smiley )

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Ask_Hjorth_Larsen

Junior Devvie




Java games rock!


« Reply #3 - Posted 2005-11-17 22:57:59 »

<? extends A> pertains to any subclass of A, true,  but only objects of ONE such subclass, and you have to decide which one it is at some time (A itself or an "actual" subclass). The smart thing is that if you create it as a Set<B>, then e.g. the get() method will automatically return objects of type B, while if you create it as Set<A> it will return objects of type A. Thus, even though you don't know what type of elements the List will get to contain, you can automatically have it return EXACTLY that type instead of some general type (like Object) which would require casts. Sorry about the headache. Now for an example:

Suppose you have a certain data structure which can only store a certain data type. For example, it could be "Tree" which can only store and return "Node" entries. Now someone wants to use your class. Perhaps they can use the getNode(...) method of the Tree class. Unfortunately, they want to store NOT JUST NODES, but actually a subclass of Node, called SpecificNode. Now when they use the getNode(...) method they will have to typecast the Nodes returned by Tree into SpecificNodes.

How do we solve this problem? We can't just call it a Tree<T>, because then it would be possible to create a Tree<Object>, and we require the Node functionality in our tree. Instead, we get the brilliant idea to call it a Tree<N extends Node>, so now you can create a Tree<SpecificNode>, Tree<Node>, Tree<TheOtherKindOfNode> and so on. The objects return by getNode(...) will always be of the correct type, and the age of class-casting has come to an end!

EDIT: important typo this time. Also, I realize that the question was more about the "?" than the "extends", but I hope it's helpful anyway
Offline swpalmer

JGO Coder


Exp: 12 years


Where's the Kaboom?


« Reply #4 - Posted 2005-11-18 02:10:05 »

I understand the "extends" part... it truly is the "?" that makes my brain hurt.

E.g.  in <? extends A>  if the ? is bound to some SPECIFIC subclass of A (or A itself) when is that done?  How can the compiler know?

eg.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
class A {}
class B extends A {}
class C extends A {}

class Test
{
  Set<? extends A> mySet;

  init_as_B() { mySet = new Set<B>(); }
  init_as_C() { mySet = new Set<C>(); }

  do_something()
  {
      if (Math.random() > 0.5)
         init_as_B();
      else
         init_as_C();
      // which line fails?
      mySet.add(new B());
      mySet.add(new C());
      mySet.add(new A());
  }
}

Offline Ask_Hjorth_Larsen

Junior Devvie




Java games rock!


« Reply #5 - Posted 2005-11-18 12:50:09 »

I think I have a better example then Smiley

The following code is legal:
1  
2  
String[] strings = new String[17];
Object[] objects = strings;

I.e., String[] is a subclass of Object[]. However, consider the code
1  
2  
List<String> stringList = new ArrayList<String>();
List<Object> objectList = stringList;

This is illegal, i.e. List<String> is not a subclass of List<Object>.

With this in mind, let's go back to the classes of the previous example. What if we need to access some stuff which is found in class Node? We can't just pass a List<Node> as parameter, because some day the user will want to use our function on a List<SpecificNode>, which is not a subclass of the former. What, then, is the proper superclass of all Lists containing some kind of Node? It's List<? extends Node>. Now, if we declare the list parameter as such in the method signature, everything will work. As opposed to a List<Node>, we can't insert new elements into the list because we don't know the correct type. Still we can access the contents since we know they are all a subclass of Node.
Offline swpalmer

JGO Coder


Exp: 12 years


Where's the Kaboom?


« Reply #6 - Posted 2005-11-18 15:09:05 »

Ah.. I think I get it.

Can we say then that a declaration using the wildcard syntax is intended for mostly read access to that object.
Write access that will pass objects in generally requires a concrete parameterized type e.g.
1  
2  
3  
4  
class MyClass<T> {
  Set<T extends As;
  add(T a) { s.add(a); }
}


The obvious write access that is allowed would involve things that don't really care about the true type, like remove(Object x) and clear().

Offline Ask_Hjorth_Larsen

Junior Devvie




Java games rock!


« Reply #7 - Posted 2005-11-19 01:26:04 »

Yeah, except I don't think you can use <T extends A> like that (though I haven't checked). There's a problem as to what class A actually is, because there is no possible way to select A when you create the MyClass object. What you may actually have been thinking is encompassed in the following:

1  
2  
3  
4  
class MyClass<T> {
  Set<? super T>  s;
  add(T a) { s.add(a); }
}


Now we can surely add elements, because any T-type object is automatically a subclass of whichever kind of stuff is actually stored in the set. However, we cannot use the methods declared in T, because the contents of the set they may not actually be of type T. Now we have the opposite problem as compared to before.
Offline swpalmer

JGO Coder


Exp: 12 years


Where's the Kaboom?


« Reply #8 - Posted 2005-11-19 21:27:52 »

I think I can do this:
1  
2  
3  
4  
class MyClass<T extends A> {
  Set<T>  s;
  add(T a) { s.add(a); }
}


I put the 'extends' in the wrong spot in my previous example.

I don't understand your example  using 'super'

1  
2  
3  
4  
class MyClass<T> {
  Set<? super T>  s;
  add(T a) { s.add(a); }
}


You say that any T-type object is automatically a SUBCLASS of the stuff actually stored in the set.  Is it not the opposite?  Any T-type object is automatically a SUPERCLASS of what is stored in the set, and therefore you don't know if it is a compatible object to what is in the set.

Offline Ask_Hjorth_Larsen

Junior Devvie




Java games rock!


« Reply #9 - Posted 2005-11-20 01:08:48 »

1  
You say that any T-type object is automatically a SUBCLASS of the stuff actually stored in the set.  Is it not the opposite?  Any T-type object is automatically a SUPERCLASS of what is stored in the set, and therefore you don't know if it is a compatible object to what is in the set.


In the case <? extends T>, "?" is a subclass of "T". In the case <? super T>, "T" is a subclass of "?". Therefore it is in the previous example correct that T is a subclass of whichever type ("?") is actually stored in the set. My previous comment should thus still be true. I have, however, not written code which used <? super T> so excuse me if I'm wrong about something.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline swpalmer

JGO Coder


Exp: 12 years


Where's the Kaboom?


« Reply #10 - Posted 2005-11-20 06:53:31 »

I think you are right... it was just my brain getting twisted again. Smiley

Offline Ask_Hjorth_Larsen

Junior Devvie




Java games rock!


« Reply #11 - Posted 2005-11-20 16:22:42 »

By the way, thanks for the discussion! I've learned a lot of stuff, just talking about these things.
Offline swpalmer

JGO Coder


Exp: 12 years


Where's the Kaboom?


« Reply #12 - Posted 2005-11-20 17:05:15 »

You're welcome.  Thanks for the answers Smiley

I think I have figured out part of why I keep getting confused.  My brain parses <? extends T> and <? super T> the same.  It is reading <? super T> as '?' has super type 'T', which is of course wrong and exactly the same as <? extends T>.  I think it is just the left to right order is doing it.

I suppose if it was written like this:  <T extends ?> and remove the need for 'super' entirely, then my brain would be a little happier.  That does convey the same meaning as <? super T>, right?

Offline Ask_Hjorth_Larsen

Junior Devvie




Java games rock!


« Reply #13 - Posted 2005-11-20 18:23:27 »

1  
2  
3  
I think I have figured out part of why I keep getting confused.  My brain parses <? extends T> and <? super T> the same.  It is reading <? super T> as '?' has super type 'T', which is of course wrong and exactly the same as <? extends T>.  I think it is just the left to right order is doing it.

I suppose if it was written like this:  <T extends ?> and remove the need for 'super' entirely, then my brain would be a little happier.  That does convey the same meaning as <? super T>, right?


The above seems reasonable. For a while I also wondered why they didn't use <? extends T> and <T extends ?>. Maybe because those two variations look too much like each other. Programmers could easily make mistakes, since one of them seems somewhat more common than the other.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

trollwarrior1 (27 views)
2014-11-22 12:13:56

xFryIx (69 views)
2014-11-13 12:34:49

digdugdiggy (48 views)
2014-11-12 21:11:50

digdugdiggy (42 views)
2014-11-12 21:10:15

digdugdiggy (36 views)
2014-11-12 21:09:33

kovacsa (60 views)
2014-11-07 19:57:14

TehJavaDev (64 views)
2014-11-03 22:04:50

BurntPizza (62 views)
2014-11-03 18:54:52

moogie (77 views)
2014-11-03 06:22:04

CopyableCougar4 (77 views)
2014-11-01 23:36:41
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!