3

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?

PalidinoDH
  • 93
  • 11
  • 1
    If you're implementing `NameableContainer`, you need to provide a type argument that implements `Nameable`. Currently you are not doing that. – Logan Mar 12 '19 at 03:51

1 Answers1

2

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>
//                               ^^^^^^^^^^^^^^^^^^^^                             ^^^
Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
  • 1
    In this case, using raw types would indeed produce error. You can still use raw types in other code, though. It is just discouraged. – Logan Mar 12 '19 at 03:56
  • You can use raw types but it will always throw the compiler off. It's really unfortunate that it's still not an error by default in javac as it's the cause of many hard-to-trace problems in code. I've added a link to an insightful Q&A on SO about this. – Erwin Bolwidt Mar 12 '19 at 03:57
  • Yeah, the main reason they allowed raw types is because of compatibility. Most code would have made the transition to generics by now, but I'm sure there is still code in production that uses raw types. – Logan Mar 12 '19 at 03:59
  • Sorry, I didn't include all the code, that was my fault. Compiling with the changes to NameableMap produces the error error: findByName(Name) in NameableMap cannot implement findByName(Name) in NameableContainer return type Nameable is not compatible with T#2 where T#1,T#2 are type-variables: T#1 extends Nameable declared in interface NameableContainer T#2 extends Nameable declared in class NameableMap – PalidinoDH Mar 12 '19 at 04:29
  • Without seeing your code I can't tell the problem. Maybe you forgot the `` in `implements NameableContainer`. Or maybe you introduced another method-local type variable on method `findByName` in `NameableMap`. – Erwin Bolwidt Mar 12 '19 at 04:36
  • Raw type is a disease. – Vishwa Ratna Mar 12 '19 at 04:41
  • Figured it out, thanks for the help! In the NameableMap class I also had this method inherited from NameableContainer, T findByName(Name name);. I was previously using it as Nameable findByName in NameableContainer, needed to change Nameable to T. – PalidinoDH Mar 12 '19 at 04:43