I'm having trouble actually inheriting the interface. I keep ending up with the error
error: NameableContainer cannot be inherited with different arguments: < Friend> and <>
I have the following interfaces:
public interface Nameable
public interface Name
public interface Friend extends Nameable
public interface NameableContainer<T extends Nameable> {
void add(Name name, Name prevName);
void remove(Nameable nameable);
T findByName(Name name);
}
public interface FriendContainer extends NameableContainer<Friend>
I also have an abstract class that inherits NameableContainer.
public abstract class NameableMap implements NameableContainer {
public void add(Name name, Name prevName) { /* do stuff*/ }
public void remove(Nameable nameable) { /* do stuff*/ }
public Nameable findByName(Name name) { /* do stuff*/ }
}
And finally, trying to put these all together
public class Friends extends NameableMap implements FriendContainer
What am I missing?
You are using raw types when you say
public abstract class NameableMap implements NameableContainer
That throws everything off in the compiler; raw types are an error unless your code was originally written for java 1.4 or earlier. When you implement an interface that specifies a type argument, you either need to provide a concrete type, or if that isn't known yet, you can introduce another type parameter and pass it to the supertype.
See: What is a raw type and why shouldn't we use it?
So you specify a variable generic type parameter when you implement NameableContainer (since you don't know the concrete type yet as NameableMap should also work for all Nameables.
public abstract class NameableMap<T extends Nameable> implements NameableContainer<T>
// ^^^^^^^^^^^^^^^^^^^^ ^^^
move all the code from the entire program to one class and put it onto one line
Related
Consider the following situation:
public abstract class AnimalFeed{
}
public class FishFeed extends AnimalFeed{
}
public class BirdFeed extends AnimalFeed{
}
public abstract class Animal{
public void eat(AnimalFeed somethingToEat)
}
Now I would like to define a class "Bird" extending "Animal" being sure that when the bird eats, it eats only BirdFeed.
One solution would be to specify a sort of contract, in which the caller of "eat" must pass an instance of the appropriate feed
public class Bird extends Animal{
#Override
public void eat(AnimalFeed somethingToEat){
BirdFeed somethingGoodForABird
if(somethingToEat.instanceOf(BirdFeed)){
somethingGoodForABird = (BirdFeed) somethingGoodForABird
}else{
//throws error, complaining the caller didn't feed the bird properly
}
}
}
Is it acceptable to delegate the responsibility of the parameter to the caller? How to force the caller to pass a specialization of the parameter? Are there alternative design solutions?
You'd need to add a type variable to the class:
public abstract class Animal<F extends AnimalFeed> {
public abstract void eat(F somethingToEat);
}
Then you can declare your subclasses as wanting a particular type of AnimalFeed:
public class Bird extends Animal<BirdFeed> {
public void eat(BirdFeed somethingToEat) {}
}
public class Fish extends Animal<FishFeed> {
public void eat(FishFeed somethingToEat) {}
}
What you are asking for doesn't make sense from an theoretical point of view.
Restricting a method parameter violates the Liskov Substitution Principle.
The idea there: any occurance (usage) of some base class object must be able to deal with some sub class object, too.
A more simple example: when your base interface goes:
void foo(Number n)
then you must not do
#Override
void foo(Integer i)
in a subclass. Because all of a sudden, a caller
someObject.foo(someNumber)
would run into ugly ugly problems when someObject is of that derived class; which only accepts Integers, but not Numbers.
In other words: good OO design is much more than just writting down A extends B. You have to follow such rules; or you end up with systems are already broken on a conceptual point!
And for the record: it is theoretically valid to widen method parameters (in general, but in Java); and it is also ok to restrict the return types of methods (because these changes can not break client code; and that even works in Java).
Long story short: the answer here is too change your design; for example by using Generics and dependent interfaces to somehow create a relationship between the Animal and the Feed class hierarchy.
I am trying to write an Interface with a setter method that takes in a TreeMap as an argument.
That TreeMap can have objects of classes descended from an AbstractNResource class. The class definition of AbstractNResource is written with generics to let it take in two arguments from two other class hierarchies.
I have had trouble writing a setter method in the Interface that the compiler will accept.
Here is the Interface (with the compile error), I call it IDataLoader:
public interface IDataLoader {
public abstract void setFrameDataMap(
// Compile Error: Syntax error on token "extends", , expected
TreeMap<Long, AbstractNResource<AbstractNRequestableResourceData, INDescriptor>.AbstractFrameData> frameDataMap);
}
This is the parent class of the kind of objects that TreeMap can have:
public abstract class AbstractNResource<T extends AbstractNRequestableResourceData, D extends INDescriptor>
extends
AbstractVizResource<AbstractNRequestableResourceData, IDescriptor>
implements INResource {
public abstract class AbstractFrameData {}
protected TreeMap<Long, AbstractFrameData> frameDataMap;
}
Next step down, I have an AbstractDataLoader class that partially implements the Interface IDataLoader:
public abstract class AbstractDataLoader<T extends AbstractNatlCntrsRequestableResourceData, D extends INatlCntrsDescriptor>
implements
IDataLoader<AbstractNatlCntrsRequestableResourceData, INatlCntrsDescriptor> {}
One more step down I have a class WaveSatDataLoader that extends that abstract class. This is where the compile error is happening:
public class WaveSatDataLoader extends
AbstractDataLoader<WaveSatResourceData, NCMapDescriptor> {
#Override
public void setFrameDataMap(TreeMap<Long,AbstractNatlCntrsResource<WaveSatResourceData, NCMapDescriptor>.AbstractFrameData> frameDataMap) {
System.out.println("To do");
}
}
The compilation error is:
The method
setFrameDataMap(TreeMap.AbstractFrameData>)
of type WaveSatDataLoader must override or implement a supertype
method
I do not have setFrameDataMap() implmentation in the AbstractDataLoading class, but putting one there hasn't helped.
I am stumped as to why the compiler is complaining.
Any help would be greatly appreciated
Thanks
The compiler is complaining because you are trying to implement an interface method with a method that has a different signature.
In IDataLoader, the second type parameter of the argument to setFrameDataMap is
AbstractNResource<AbstractNRequestableResourceData, INDescriptor>.AbstractFrameData
whereas in WaveSatDataLoader it is
AbstractNatlCntrsResource<WaveSatResourceData, NCMapDescriptor>.AbstractFrameData
I am also confused about whether IDataLoader is supposed to be generic or not. You have written
implements IDataLoader<AbstractNatlCntrsRequestableResourceData, INatlCntrsDescriptor>
yet in the first section of code IDataLoader does not have type parameters.
I'm trying to understand how to use generics in the form of a bounded type parameter in an interface. In this case, to avoid casting when using the bounded param in concrete implementations but I'm running into an issue. I will use the following example to illustrate my problem:
There's an interface and two concrete implementations
public abstract class Publication {
}
public class Newspaper extends Publication {
}
public class Newspaper extends Publication {
}
Then we have an interface representing a publishing house with two concrete implementations, one publishes magazine and the other newspapers
public interface Publisher {
public <T extends Publication >void publish(T publication);
}
Here are the two implementations
//DOES NOT COMPILE
public class MagazinePublisher implements Publisher{
#Override
public void publish(Magazine publication) {
//do something with the magazine, its already the type we need without casting
}
}
//COMPILES but a cast is required to get the type I want
public class NewsPaperPublisher implements Publisher{
#Override
public void publish(Publication publication) {
// Now I need to cast
Newspaper newspaper = (Newspaper)publication;
//Do some stuff here
}
}
The example maybe a bit contrived... I understand why the MagazinePublisher class doesn't compile: I'm trying to implement the method with a more specific class than defined by the contract of the publish method in the interface. So how do I user generics to avoid the cast in the NewsPaperPublisher class's publish() method?
You want to make the interface generic.
public interface Publisher <T extends Publication> {
void publish(T publication);
}
Then, instead of NewspaperPublisher and MagazinePublisher, you can just write Publisher<Newspaper> and Publisher<Magazine>.
Or if you want to provide different implementations depending on the type, you can write things like
public class NewspaperPublisher implements Publisher<Newspaper> {
#Override
public void publish(Newspaper publication) {
// do some stuff
}
}
Say I'm making a class that implements an interface, and have code like this:
public void setGoalLocation(Location loc)
{
goal = loc;
}
The code doesn't compile, because it demands that I implement a "setGoalLocation(Ilocation loc)" method, where "Ilocation" is an interface and "Location" is an actual concrete class that implements it.
This means that I have to do something like this:
public void setGoalLocation(ILocation loc)
{
goal = (Location)loc;
}
That just seems really awkward. And funnily enough, Java doesn't seem to care about other methods returning Location instead of the interface ILocation. This works:
public Location getStartLocation()
{
return start;
}
...even though the "required" method would be a "public ILocation getStartLocation". Can anyone explain why this is, and any help for making the code less awkward? I'd like to be able to use a Location as a parameter, not an ILocation.
The problem is that the interface requires a method that accepts anything as an argument that is a subtype of ILocation, not just an object of the specific type Location. If you had another concrete type Position that was a subtype of ILocation, then implementing the interface would require you to accept a Position object as well as a Location object.
Note that in your work-around using a cast, you'd get a ClassCastException at run time if you happened to pass a Position instead of a Location object.
As a design issue, to get around this you could define your interface as a generic:
interface <T extends ILocation> TheInterface {
void setGoalLocation(T loc);
}
Then your concrete class can bound the generic parameter:
public class MyClass implements TheInterface<Location> {
public void setGoalLocation(Location loc) {
. . .
}
}
As to return types, that works because any Location object is an ILocation, so when you return a Location you are returning an ILocation.
Java supports covariant return types where the return type of a method in a subclass (or interface implementation) can return a subclass (or implementation) of the declared type. So in general, the following is allowed
public class A {}
public class B extends A {}
public class C {
A getSomething();
}
public class D extends C {
B getSomething();
}
If the interface has a method that takes an interface type, you cannot override it with a different signature.
public interface I {
void setSomething(ISomething somethingInterface);
}
You cannot do
public class Something implements ISomething {}
public class MyI implements I {
void setSomething(Something somethingInterface);
}
Given an interface like this
public interface MyInterface1<T extends MyAbstractClass> {
...
}
I want to make another interface MyInterface2 taking a MyInterface1 as a generic type and in MyInterface2 I want to reference the actual types of the actual MyInterface1
public interface MyInterface2<INTERFACE extends MyInterface1<MYCLASS>> {
MYCLASS returnInstanceOfMyClass();
}
So I want to say that method "returnInstanceOfMyClass" returns the actual T of the actual MyInterface1 given to MyInterface2.
The thing is that I am not allowed to write the following
public interface MyInterface2<INTERFACE extends MyInterface1<MYCLASS>> {
I am allowed to write
public interface MyInterface2<INTERFACE extends MyInterface1<?>> {
but then I am not able to reference the actual type of T in MyInterface1 in the method signature in MyInterface2 - because I have given it no name to be used when referencing.
I want to be able to do the following in a type-safe way
class MyClass extends MyAbstractClass {
...
}
MyClass c = new MyInterface2<MyInterface1<MyClass>>.returnInstanceOfMyClass();
No casting to MyClass should be necessary, because it can see that the actual class of MyInterface1 given to MyInterface2 is MyClass, and that is what is returned from returnInstanceOfMyClass.
How to do that?
You need a second generic parameter:
public interface MyInterface2<U estends MyAbstractClass, T extends MyInterface1<U>> {
U returnInstanceOfMyClass();
}