Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You're tripping over the fact that Java generics are not polymorphic on the type parameter.</p> <p>Talking through your code fragment, let's pull the example apart:</p> <pre><code>protected List&lt;GreyHound&gt; greyHounds; // List&lt;GreyHound&gt; is fine /** This method returns a lovely List of GreyHounds */ public List&lt;GreyHound&gt; getGreyHounds() { return this.greyHounds; } /** Here is the problem. A List&lt;GreyHound&gt; is not a List&lt;Dog&gt; */ public List&lt;Dog&gt; getDogs() { return getGreyHounds(); //compiler error } </code></pre> <p>So your original comment is correct. The two Lists are definitely different with no inheritance between them. So, I would suggest that you investigate these two options:</p> <ol> <li><p>Try returning a new list as you suggest in your comment. For example, <code>return new ArrayList&lt;Dog&gt;(this.greyHounds);</code></p></li> <li><p>Do you really need to keep a list of a specific breed of Dog? Perhaps you should define the data member to be a <code>List&lt;Dog&gt;</code> to which you add your specific GreyHounds. I.e., <code>protected List&lt;Dog&gt; greyHoundsOnly;</code> where you manage which dogs are allowed in the kennel via the object's external interface.</p></li> </ol> <p>Unless you have a good reason to keep a type-specific list, I would think seriously about option 2.</p> <p>EDIT: fleshing out my suggested options above:</p> <p>Option 1: <strong>Return a new list</strong>. Pros: Simple, straightforward, you get a typed list out and it eliminates a thread-safety problem (doesn't expose an internal reference to the world). Cons: seemingly a performance cost.</p> <pre><code>// Original code starts here. public interface DogKennel { public List&lt;Dog&gt; getDogs(); } public class GreyHoundKennel implements DogKennel { protected List&lt;GreyHound&gt; greyHounds; public List&lt;GreyHound&gt; getGreyHounds() { return this.greyHounds; } // Original code ends here public List&lt;Dog&gt; getDogs() { // This line eliminates the thread safety issue in returning // an internal reference. It does use additional memory + cost // CPU time required to copy the elements. Unless this list is // very large, it will be hard to notice this cost. return new ArrayList&lt;Dog&gt;(this.greyHounds); } } </code></pre> <p>Option 2: <strong>Use a different data representation</strong>. Pros: plays nicer with polymorphism, returns the generic list that was the original goal. Cons: it's a slightly different architecture which may not fit with the original task.</p> <pre><code>public abstract class DogKennel { protected List&lt;Dog&gt; dogs = new ArrayList&lt;Dog&gt;(); } public class GreyHoundKennel extends DogKennel { // Force an interface that only allows what I want to allow public void addDog(GreyHound greyHound) { dogs.add(greyHound); } public List&lt;Dog&gt; getDogs() { // Greatly reduces risk of side-effecting and thread safety issues // Plus, you get the generic list that you were hoping for return Collections.unmodifiableList(this.dogs); } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload