I have created the following interface
public interface ISolutionSpace {
public boolean isFeasible();
public boolean isSolution();
public Set<ISolutionSpace> generateChildren();
}
However, in the implementation of ISolutionSpace in a class called EightQueenSolutionSpace, I am going to return a set of EightQueenSolutionSpace instances, like the following stub:
#Override
public Set<ISolutionSpace> generateChildren() {
return new HashSet<EightQueenSolutionSpace>();
}
However this stub wont compile. What changes do I need to make?
EDIT: I tried 'HashSet' as well and had tried using the extends keyword. However since 'ISolutionSpace' is an interface and EightQueenSolutionSpace is an implementation(and not a subclass) of 'ISolutionSpace', it is still not working.
Two possibilities:
#Override
public Set<? extends ISolutionSpace> generateChildren() {
return new HashSet<EightQueenSolutionSpace>();
}
Or
#Override
public Set<ISolutionSpace> generateChildren() {
return new HashSet<ISolutionSpace>();
}
and simply add instances of EightQueenSolutionSpace to the set.
Mind you, inheritance and other object hierarchy features don't exactly work like expected in generics.
But it's not your only problem : you try to return an ArrayList as an implementation of Set, which can't work !
Concerning the generics part, when you write Set<ISolutionSpace>, you say to the compiler you want a collection of instances of ISolutionSpace, but not of possible subclasses of ISolutionSpace. To be allowed to use subclasses, you'll have to use ? extends ISolutionSpace, which precisely says "accept any subclass of ISolutionSpace".
So, to have a valid code, you'll have to change both your interface and your implementation.
Your interface should become
public interface ISolutionSpace {
public boolean isFeasible();
public boolean isSolution();
public Set<? extends ISolutionSpace> generateChildren();
}
And your implementation
#Override
public Set<? extends ISolutionSpace> generateChildren() {
//for()
return new HashSet<EightQueenSolutionSpace>();
}
return new HashSet<ISolutionSpace>();
All the references in the HashSet can point to EightQueenSolutionSpace instances, but the generic type should be ISolutionSpace.
Set and List are different types of collections.
You could either change your declaration to return a list, or change the return parameter class to an implementation of Set (HashSet, TreeSet...)
According to the Java API:
Interface Set
All Superinterfaces: Collection
All Known Subinterfaces: SortedSet All
Known Implementing Classes:
AbstractSet, HashSet, LinkedHashSet,
TreeSet
I think you have to replace Set with List:
Interface List
All Superinterfaces: Collection
All
Known Implementing Classes:
AbstractList, ArrayList, LinkedList,
Vector
Assuming the caller would in turn work with the generic ISolutionSpace interface rather than the specific EightQueenSolutionSpace, just change the generateChildren method to public Set<? extends ISolutionSpace> generateChildren()
All the types of collection in Java is like this:
Collection
├List
│ ├LinkedList
│ ├ArrayList
│ └Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap
So it's obvious for this error. Try modify Set into List would solve this problem.
Hope this would help you.
Related
My background in C#. I want to know why Java overridden base class method expects same return type, even if we change the overridden return type to be of the base class type it throws an error. Can anyone let me know the reason for this? Please find the code snippet from below.
public class ListIterator
extends Test // Test is base for ListIterator
{
}
class Collection
{
public ListIterator iterator() throws Exception {
return new ListIterator();
}
}
class Child
extends Collection
{
//Here the return type “Test” is the base for ListIterator, but still it
//throws error to mark the return type as ListIterator. If we comment the
//extended base class "Collection" it works as expected.
public Test iterator() throws Exception {
return new ListIterator();
}
}
Firstly, no, this wouldn't work in C# - not when you're actually overriding the method. (It will work if you use new, but then you're not overriding.) C# is more strict than Java, in that the return types do have to match exactly... whereas Java allows you to return a more specific type, just not a more general one. For example, this is fine:
public class Base {
public Object getFoo() {
...
}
}
public class Child extends Base {
#Override public String getFoo() {
...
}
}
... but you're trying to do the opposite.
To show why that's dangerous, imagine that you changed your Child.iterator() method implementation to return new Test();. Then imagine someone has written:
Collection collection = new Child();
ListIterator iterator = collection.iterator();
Everything looks perfectly type-safe, because Collection.iterator() is declared to return ListIterator - but the returned value is neither null nor a reference to a ListIterator.
So basically, the answer is "Java is protecting you from shooting yourself in the foot. This is a good thing."
Subtypes must have the same or greater capabilities than their supertypes. Formally this is known as the Liskov substitution principle.
If ListIterator extends Test, then ListIterator may be more capable than Test, and presumably is, or else it would be pointless.
If Child extends Collection, then Child must not reduce the capabilities of Collection by returning a less capable type from one of its methods.
If this works in C#, then C# is broken.
I'm attempting to create an ArrayList (so java, obviously) with type TileEntity (yes this is a minecraft mod). But I also need the objects added to the ArrayList to implement a certain interface.
The first option that came to mind was creating an abstract subclass of TileEntity that implemented interface, and using that as the ArrayList type. But given the fact that people normally create their own subclasses of TileEntity and use those as the class they normally subclass, and I want people to be able to hook into my mod, I can't expect them to subclass anything besides TileEntity.
My current solution is to check if(object instanceof MyInterface) before adding, but that seems ugly. Surely there's a way to set the type of an ArrayList to require that an object be both a subclass of TileEntity and an implementor of MyInterface.
You can make generic the method or class where the ArrayList is used. For example, a generic method:
public <T extends TileEntity & MyInterface> void doStuffWith(T obj) {
List<T> yourList = new ArrayList<T>();
yourList.add(obj);
...//more processing
}
And a generic class:
public class ArrayListProcessor<T extends TileEntity & MyInterface> {
List<T> theList;
public void processList(T obj) {
theList.add(obj);
...
}
public void someOtherMethod() {
T listElem = theList.get(0);
listElem.callMethodFromTileEntity();//no need to cast
listElen.callMethodFromMyInterface();//no need to cast
}
}
...//somewherein your code
//SomeObj extends TileEntity and implements MyInterface
ArrayListProcessor<SomeObj> proc = new ArrayListProcessor<SomeObj>();
You could add whatever methods of TileEntity you need to your interface, and just make the ArrayList of your interface. There is probably some fancy way of using generics to solve the problem in a better way, but I'm unsure how.
EDIT: dcernahoschi's solution is much better.
I'm using several interfaces with generics types. While combining it together I have some problems when I have to use them from a part of the code that is unaware of the concrete type of the generic parameter.
Suppose I have the following interface:
public interface MyObjectInterface<T extends Number> {}
The object implementing that interfaceare stored in a generic collection with the same generic type:
public interface MyCollectioninterface<T extends Number> {
public void updateObject(MyObjectInterface<T> o);
}
Concrete instances of MyCollectionInterface hold several MyObjectInterface of the same generic parameter:
public class ConcreteCollection<T extends Number> implements
MyCollectionInterface<T> {
List<MyObjectInterface<T>> list;
public void updateObject(MyObjectInterface<T> o){}
}
Now, I have several questions on how to use these generic interfaces from a client class that is
(and must be) unaware of the concrete type of generics.
Suppose I have the following class:
public class ClientClass{
private MyCollectionInterface<?> collection; //1st possibility
private MyCollectionInterface collection; //2nd possibility
public ClientClass(MyCollectionInterface<?> collection){
this.collection = collection;
}
public void foo(MyObjectInterface<?> o){
this.collection.updateObject(o); //this doesn't compile
}
public void foo(MyObjectInterface<? extends Number> o){
this.collection.updateObject(o); //this doesn't compile either
}
public void bar(MyObjectInterface o){
MyObject b = o; //warning
this.collection.updateObject(o); //this compile but with warnings
}
}
First Question :
Considered the fact that ClientClass doesn't care of which concrete type extending Number is the collection, should I declare collection with or without "?" ? If I use the second version I get the following warning:
MyCollectionInterface is a raw type. References to generic type
LatticeInterface should be parameterized
Second Question :
Why method foo doesn't compile?
Third question:
It seems that I need to use bar signature to call updateObject method. Anyway this solution produce a warning while trying to assign the MyObjectInterface parameter, like in the first question. Can I remove this warning?
Last questions:
Am I doing something weird with this generic interfaces and I should refactor my code?
Do I really have to care about all these warnings?
How can I use safety a generic interface from a class where I don't know its concrete type?
Ok, I played a bit with your code and reached a conclusion.
The problem is that your ConcreteCollection (and its interface MyCollectionInterface) declare the method updateObject as receiving an argument of type MyObjectInterface<T> (where T extends Number) - note that the type is a concrete one (not a wildcard).
Now, in your client class you are receiving a collection and storing it as MyCollectionInterface<?> but the instance that is passed to ClientClass' constructor will be of a concrete type, for instance:
new ClientClass(new ConcreteCollection<Integer>());
This means that the method updateObject of that instance would only accept an argument of type MyCollectionInterface<Integer>.
Then, in method foo you are trying to pass a MyObjectInterface<?> to updateObject, but since the compiler doesn't know which generic type your collection accepts (it could be Integer like in my example but it could also be Double or any other type that extends Number), it won't allow any object to be passed.
Long story short, if you declare your reference as MyCollectionInterface<?> you won't be able to call updateObject on it. So you have two choices:
1) Pick a concrete type and stick with it:
private MyCollectionInterface<Number> collection;
public ClientClass(MyCollectionInterface<Number> collection){
this.collection = collection;
}
public void foo(MyObjectInterface<Number> o){
this.collection.updateObject(o); //compiles
}
But then you are limiting the collections you can receive in your constructor (which may not be a bad idea), or:
2) Modify your interface to accept a wildcard type:
public interface MyCollectionInterface<T extends Number> {
public void updateObject(MyObjectInterface<? extends Number> o);
}
public class ConcreteCollection<T extends Number> implements MyCollectionInterface<T> {
List<MyObjectInterface<T>> list;
public void updateObject(MyObjectInterface<? extends Number> o) {}
}
private MyCollectionInterface<?> collection;
public ClientClass(MyCollectionInterface<?> collection){
this.collection = collection;
}
public void foo(MyObjectInterface<?> o){
this.collection.updateObject(o); //compiles
}
Also, note that even in 2) you could still run into the same problem in your implementation of the updateObject method unless you declare your list something like this (with ArrayList for example):
List<MyObjectInterface<? extends Number>> list = new ArrayList<MyObjectInterface<? extends Number>>();
In which case you could as well remove the <T extends Number> from MyCollectionInterface and ConcreteCollection since T isn't used anymore.
#Your last questions:
1) Probably yes
2) You should
3) You can't, if you don't really care which objects you store in the collection, you should ditch generics altogether.
Sorry for the long answer, hope this helps.
I am calling a specific class using only its interface. The problem is, the class itself implements Comparable, but because I am referring to the class via a different interface, the compiler does not know it implements Comparable. I'm sure there is an easy solution to this... but I just can't think of it right now.
Will everything that implements the interface also implement Comparable<T>? If so, I suggest you just make the interface extend Comparable<T>.
Otherwise, you could just cast to Comparable<T> if you happen to know that in this case it will work. Of course, that loses some compile-time type safety, but that's the nature of the beast.
This seems odd to me... if you have main like the following, you can make it work with the Parent interface and Child classes below... but there is an oddity in that you could try to compare a ChildA to a ChildB which probably doesn't make sense to do.
Maybe if you gave us a hint at what the classes/interface are doing we could give a better answer.
public class Main
{
public static void main(final String[] argv)
{
Parent x;
Parent y;
x = new ChildA();
y = new ChildA();
x.compareTo(y);
}
}
abstract interface Parent
extends Comparable<Parent>
{
}
class ChildA
implements Parent
{
public int compareTo(Parent o)
{
throw new UnsupportedOperationException("Not supported yet.");
}
}
class ChildB
implements Parent
{
public int compareTo(Parent o)
{
throw new UnsupportedOperationException("Not supported yet.");
}
}
I'd suggest you to use Comapartor instead. You can use sort(list, Comparator). Your comparator implementation will cast class to Comparable and use its compare method. So the compiler will be satisfied and you will reuse the existing implementation of compare method.
You can do some freaky generics. Let's say the main interface is Lickable (which defines a method lick()), and you want a method that will process objects which are Lickable and Comparable. You write:
public <LickableAndComparable extends Lickable & Comparable<LickableAndComparable>> void lickGreater(LickableAndComparable a, LickableAndComparable b) {
if (a.compareTo(b) > 0) a.lick();
else b.lick();
}
You can then call that with objects of any type which is both Lickable and Comparable. Note that it only works if both arguments share a type which is both Lickable and Comparable to itself. If you only have one class in mind, then this should be fine. You may run into migraine-inducing compiler errors if your usage of the method gets complicated.
Comparable interfaces are tricky. In general, if you mark an interface as Comparable to itself, any correct implementation may only use methods from this interface to perform the comparison. Otherwise this relation can't be made anti-symmetric - a necessary condition to have a consistent ordering.
So think twice before marking an interface as comparable.
There is however a workaround in your case, if you are sure you are not mixing different implementations of your interface:
interface Foo {
}
interface Bar extends Foo, Comparable<Bar> {
}
class FooComparator<T extends Foo & Comparable<T>> implements Comparator<T> {
#Override
public int compare(T arg0, T arg1) {
return arg0.compareTo(arg1);
}
}
How can I have an abstract enum, or some kind of base enum?
In my common code I'd like a notion of an enum placeholder, MyItems, without tying myself to a concrete enum. Then in each of my projects I would have a concrete implementation.
E.g.
Common Code
public interface MyItems {
// Marker interface
}
Project A
public enum Items implements MyItems {
RED_CAR, BLUE_CAR, GREEN_CAR;
}
Project B
public enum Items implements MyItems {
BROWN_TREE, GREEN_TREE;
}
This seems to work, but in my common code I can't write a loop over my interface enum, since it's not an enum. In my common code I'd like to write
for (MyItems item : MyItems.values())
doSomething(item);
but I can't because my interface is just a marker interface, and it doesn't have a .values().
Any suggestions greatly appreciated. I don't know if I'm trying in completely the wrong way.
It doesn't really make sense to do this - because the values() method is static. To call it, you need to know the type you want to call it on.
The closest you could come would be to have:
public interface MyItemsFactory<T extends MyItems>
{
Iterable<T> values();
}
and then implement that in some generic way, e.g.
public class EnumFactory<T extends Enum<T> & MyItems>
implements MyItemsFactory<T>
{
private final Class<T> clazz;
public EnumFactory(Class<T> clazz)
{
this.clazz = clazz;
}
public Iterable<T> values()
{
return EnumSet.allOf(clazz);
}
}
But the basic rule is that polymorphism and static methods don't mix. In your call:
for(MyItems item : MyItems.values())
doSomething(item);
which implementation of MyItems would you expect it to iterate over? You could have loads of types implementing MyItems.
You could look into replacing the enums with the Type Safe Enum Pattern, which would allow you to implement an interface, with a values() method that returned all the values for a particular implementation.
Get the class and dig the values with Class.getEnumConstants() from it.