Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't a method take a Collection<subClass> when the method's signature is defined as Collection<class>

I have a method that takes a list of SResource objects

public static List<STriple> listTriples(List<SResource> subjects){
//... do stuff
}

Why can't I do this

List<IndexResource> resultsAsList = new ArrayList<IndexResource>();
    resultsAsList.addAll(allResults.keySet()); // I could possible not use lists and just use sets and therefore get rid of this line, but that is a different issue
List<STriple> triples = new ArrayList<STriple>();
    triples = TriplesDao.listTriples(resultsAsList);

(The compiler tells me I have to make triples use SResource objects.)

When IndexResource is a subclass of SResource

public class IndexResource extends SResource{ 
// .... class code here
}

I would have thought this has to be possible, so maybe I am doing something else wrong. I can post more code if you suggest it.

like image 246
Ankur Avatar asked Aug 06 '11 05:08

Ankur


People also ask

When a method is defined in the subclass with the same signature as a method in the super class it is known as?

When a method in a subclass has the same name, same parameters or signature, and same return type(or sub-type) as a method in its super-class, then the method in the subclass is said to override the method in the super-class. Method overriding is one of the way by which java achieve Run Time Polymorphism.

Can a subclass have a method with the same name and the same signature as its superclass?

You can write a new instance method in the subclass that has the same signature as the one in the superclass, thus overriding it. You can write a new static method in the subclass that has the same signature as the one in the superclass, thus hiding it.

Which declaration prevents creating a subclass of a top level Dass?

You can prevent a class from being subclassed by using the final keyword in the class's declaration.

Can a superclass access subclass variables?

Rule:A subclass inherits all of the member variables within its superclass that are accessible to that subclass (unless the member variable is hidden by the subclass). inherit those member variables declared with no access specifier as long as the subclass is in the same package as the superclass.


2 Answers

You can do it, using wildcards:

public static List<STriple> listTriples(List<? extends SResource> subjects){
    //... do stuff
}

The new declaration uses a bounded wildcard, which says that the generic parameter will be either an SResource, or a type that extends it.

In exchange for accepting the List<> this way, "do stuff" can't include inserting into subjects. If you're just reading from the subjects in the method, then this change should get you the results you want.

EDIT: To see why wildcards are needed, consider this (illegal in Java) code:

List<String> strings = new ArrayList<String>();
List<Object> objList = string; // Not actually legal, even though string "is an" object
objList.add(new Integer(3)); // Oh no! We've put an Integer into an ArrayList<String>!

That's obviously not typesafe. With wilcards, though, you can do this:

List<String> strings = new ArrayList<String>();
string.add("Hello");
List<? extends Object> objList = strings; // Works!
objList.add(new Integer(3)); // Compile-time error due to the wildcard restriction
like image 67
dlev Avatar answered Nov 16 '22 04:11

dlev


You can't do this because generics are not "covariant" i.e. a List<Integer> is not a sub-class of the List<Number> though Integer is a sub-class of Number.

like image 38
Sanjay T. Sharma Avatar answered Nov 16 '22 02:11

Sanjay T. Sharma