error overriding method of class that extends generic class - java

i have a class A that extends a class B and the class B extends a generic Class
my class A is:
public class MyCustomerReviewConverter<SOURCE extends CustomerReviewModel, TARGET extends ReviewData> extends CustomerReviewConverter{
#Override
public void populate(final SOURCE source, final TARGET target) {.....}
the extended class B is
public class CustomerReviewConverter extends AbstractPopulatingConverter<CustomerReviewModel, ReviewData>{
#Override
public void populate(final CustomerReviewModel source, final ReviewData target)
{..........}
but i'm getting the error
Name clash: The method populate(SOURCE, TARGET) of type MyCustomerReviewConverter<SOURCE,TARGET> has the same erasure as populate(CustomerReviewModel, ReviewData) of type
CustomerReviewConverter but does not override it
what's wrong?
As second parameter in the populate method i have to pass a class
MyReviewData extends ReviewData{...}
thanks in advance
Andrea

Tricky and difficult to explain.
The type parameters are defined in the generic AbstractPopulatingConverter.
The type parameters are concretized in CustomerReviewConverter.
Then, you try to make the concretized type parameters generic again in MyCustomerReviewConverter.
And that just doesn't work. You're trying to override a method with a method that has a different method signature (different parameter types).
The only way you can override that method is as follows:
#Override
public void populate(final CustomerReviewModel source,
final ReviewData target) { /* ... */ }
However, instead of overriding the method, you can overload it:
public void populate(final MyCustomerReviewModel source,
final MyReviewData target) { /* ... */ }
If the populate() method is called on an object of type MyCustomerReviewConverter with a MyCustomerReviewModel and MyReviewData parameter, the compiler will select the most specific populate method, being the overloaded one.

The types of the generic types for <SOURCE, TARGET> have already been concreted in by B as <CustomerReviewModel, ReviewData>.
If you want to extend B, your A should simply be:
public class MyCustomerReviewConverter extends CustomerReviewConverter {
#Override
public void populate(final CustomerReviewModel source, final ReviewData target)
{ ... }
}
Otherwise you need to extend AbstractPopulatingConverter directly, and perhaps write a delegate to perform the shared logic within B so you can re-use it elsewhere.
#Robby Cornelissen explains it better than me in his answer though.

You should extend CustomerReviewConverter<SOURCE, TARGET> (probably, you haven't added its definition to the question) instead of the raw type. Then you need to override public void populate(SOURCE source, TARGET target).

Related

Java cannot be inherited with different arguments

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

Cannot implement abstract method with a subclass of an abstract argument

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);
}

How to use subtypes? - overriding and inheriting in Java

I've got problem in my code in Java. I have four(important) Classes:
public class RDOutput extends OutputType
public class RDAnalysis extends AnalysisProperties
Now I'm trying to make a method in Analysis properties:
public abstract void display(ArrayList<? extends OutputType> results);
The main problem list, the objects in the ArrayList will be different subtypes of OutputType. In my class RDAnalysis I try to make specific overriding:
public void display(ArrayList<RDOutput> results) {
but eclipse says: Name clash: The method display(ArrayList) of type RDAnalysis has the same erasure as display(ArrayList? extends OutputType) of type AnalysisProperties but does not override it
I'm not familiar with Java tricks, I tried searching in documentation and I didn't find any solution to this problem.
My question is: Is that trick that I'm doing (Basic type in abstract and Extended in final function) possible in Java (if yes, how can I do that?) or do I have to make some enum to solve this?
I suggest you to introduce generic parameter to your class and use it to parametrize your method:
public abstract class A<T extends OutputType> {
public abstract void display(ArrayList<T> results);
}
public class B extends A<RDOutput> {
public void display(ArrayList<RDOutput> results) {}
}
It's because your display doesn't cover every case of the abstract method. Maybe try something like this :
public class RDOutput extends OutputType {}
public class OutputType {}
public abstract class AnalysisProperties<T extends OutputType> {
public abstract void display(ArrayList<T> results);
}
public class RDAnalysis extends AnalysisProperties<RDOutput> {
#Override
public void display(final ArrayList<RDOutput> results) {
}
}
The problem is that you try to override a method while restricting possible parameters.
=> ArrayList<? extends OutputType> accepts more possible elements than ArrayList<RDOutput> since RDOutput extends OutputType.
You break the rule that says: the concerned subclass method has to encompass at least elements of superclass one and NEVER restrict them.
So compiler avoid to valid this override.
By the way, avoid to type your reference with concrete values like ArrayList.
What about a LinkedList passed as arguments? ... prefer a more generic relevant type like List.
Problem here is that, after type erasure comes into play, the signature of the two methods are undistinguishable: they have the same return type and they can both accept a ArrayList<RDOutput> but the first one (the generic one) can also accept any ArrayList<T extends OutputType>.
This mean that, although the JVM won't be able to choose which one to call at runtime if you pass an ArrayList<RDOutput>, at the same time your display method does not override the abstract one because your method only work for lists of RDOutput, so if you pass a List<T extends OutputType> with T != RDOutput your specific implementation doesn't accept it.
You should consider using a type parameter on the whole class as suggested in other answers, or accept the fact that you won't be able to use any RDOutput specific methods in your display method without a cast.
if a method is expecting ArrayList<? extends OutputType>
ArrayList<RDOutput> cannot be passed to it, as parent type allows any child class of OutputType in arraylist.
consider a code like this
AnalysisProperties properties = new RDAnalysis();
properties.display(arraylist consisting of any child class of OutputType); //this line will cause runtime problems

Overriding non-parameterized classes nested in a parameterized outer class in Java

Can someone please help with the syntax of subclassing a non-parameterized nested class inside a parameterized outer class, like the following?
public abstract class Foo<T> {
public class Bar {
Set<T> aSet;
}
abstract class Baz {
abstract void doSomething(Map<? extends Bar, T> aMap);
}
}
Then in a separate file, I'm not entirely sure how to define the type variable S here without parameterizing ConcreteBaz. And I can't use a wildcard variable like extends Foo<?>.Baz (I think) because I need access to that generic type variable in the doSomething method:
public class ConcreteBaz extends Foo<S>.Baz { // compilation error
public ConcreteBaz(Foo<S> foo) { foo.super(); }
public void doSomething(Map<? extends Foo<S>.Bar, S> aMap) { ... }
}
Can someone please help me figure out a way around this? Thanks.
Declare S as a type parameter:
public class ConcreteBaz<S> extends Foo<S>.Baz {
Otherwise the compiler will think S is a concrete type instead of a type parameter.
Complete example:
public class ConcreteBaz<S> extends Foo<S>.Baz {
public ConcreteBaz(Foo<S> foo) {
foo.super();
}
#Override
void doSomething(Map<? extends Foo<S>.Bar, S> aMap) {
// ...
}
}
Your problem is that the nested class is nonstatic. I'll check it out, but I'm pretty sure you cannot subclass such classes, except maybe if nested in the same class, or when creating an anonymous type.
Is declaring the nested class static viable? Them it would definitely work.
Edit: scratch all that. I don't have a compilation error. What is S in your case? You do realize you have to pass a concrete class to Foo, and cannot leave it parametrized with an unknown parameter S?
If ConcreteBaz needs to refer to the type parameter, that implies that it needs the type parameter itself:
public class ConcreteBaz<S> extends Foo<S>.Baz {

Java generic method inheritance and override rules

I have an abstract class that has a generic method and I want to override the generic method by substituting specific types for the generic parameter. So in pseudo-code I have the following:
public abstract class GetAndParse {
public SomeClass var;
public abstract <T extends AnotherClass> void getAndParse(T... args);
}
public class Implementor extends GetAndParse {
// some field declarations
// some method declarations
#Override
public <SpecificClass> void getAndParse(SpecificClass... args) {
// method body making use of args
}
}
But for some reason I'm not allowed to do this? Am I making some kind of syntax error or is this kind of inheritance and overriding not allowed? Specifically I'm getting an error about #Override because the eclipse IDE keeps reminding me to implement getAndParse.
Here's how I want the above code to work. Somewhere else in my code there is a method that expects instances of objects that implement GetAndParse which specifically means that they have a getAndParse method that I can use. When I call getAndParse on that instance the compiler checks to see whether I have used specific instances of T in the proper way, so in particular T should extend AnotherClass and it should be SpecificClass.
What we are having here is two different methods with individual type parameters each.
public abstract <T extends AnotherClass> void getAndParse(Args... args);
This is a method with a type parameter named T, and bounded by AnotherClass, meaning each subtype of AnotherClass is allowed as a type parameter.
public <SpecificClass> void getAndParse(Args... args)
This is a method with a type parameter named SpecificClass, bounded by Object (meaning each type is allowed as a type parameter). Do you really want this?
Is the type parameter used inside Args? I think the problem would be there.
The meaning of
public abstract <T extends AnotherClass> void getAndParse(T... args);
is that the caller of the method can decide with which type parameter he wants to call the method, as long as this is some subtype of AnotherClass. This means that in effect the method can be called with any objects of type AnotherClass.
Since the caller can decide the type parameter, you can't in a subclass narrow down the parameter type to SpecificClass - this would not be an implementation of the method, but another method with same name (overloading).
Maybe you want something like this:
public abstract class GetAndParse<T extends AnotherClass> {
public SomeClass var;
public abstract void getAndParse(T... args);
}
public class Implementor extends GetAndParse<SpecificClass> {
// some field declarations
// some method declarations
#Override
public void getAndParse(SpecificClass... args) {
// method body making use of args
}
}
Now the getAndParse method implements the parent class' method.
You are seeing this problem because of the concept called "Erasure" in Java Generics.
Java uses "erasure" to support backward compatibility. i.e Java code which did not use generics.
Erasure Procedure:
The compiler will first do a type checking and then it will remove(erase) all the type parameters as much as possible, and also insert TypeCasting where ever necessary.
example:
public abstract <T extends AnotherClass> void getAndParse(T paramAnotherClass);
will become
public abstract void getAndParse(AnotherClass paramAnotherClass);
In class "Implementor.java",
The code
public <SpecificClass> void getAndParse(T paramAnotherClass)
will become
public void getAndParse(SpecificClass paramAnotherClass){ }
the compiler will see that you have not implemented the abstract method correctly.
There is a type mismatch between the abstract method and the implemented method. This is why you are seeing the error.
More details can be found here.
http://today.java.net/pub/a/today/2003/12/02/explorations.html
You cannot override to specific type T because there is in fact (at the bytecode level if you wish) only one method getAndParse because of type erasure (see other answer):
public abstract void getAndParse(AnotherClass... args); // (1)
For every type of T, the same method is used.
You can overload it (I think):
public void getAndParse(SpecificClass... args); // (2)
but this will not a different method from (1) ant it will not be called by generic code:
T x = whatever;
object.getAndParse(x); // Calls (1) even if T is derived from SpecificClass
No, it's not valid. What would happen if someone with a GetAndParse reference called it with a different class extending AnotherClass?
That becomes a nonsense when someone has a reference to type GetAndParse and tries to call the getAndParse method. If Cat and Dog extend AnotherClass. I should expect to be able to call GetAndParse#getAndParse with either a Cat or a Dog. But the implementation has tried to restrict it and make it less compatible!
Static method can't override
class Vehicle{
static void park(int location){
System.out.println("Vehicle parking..");
}}
class Car extends Vehicle{
#Override //error
void park(int location) { //error
System.out.println("Car Parking..");
}}
Private method can't override
class Vehicle{
private void park(int location){
System.out.println("Vehicle parking..");
}
void callPark(){
park(100);
}}
class Car extends Vehicle{
//#Override
void park(int location) {
System.out.println("Car Parking..");
}}
class Demo {
public static void main(String[] args) {
Vehicle v1=new Car();
v1.callPark();
}}
Final method can't override
class Vehicle{
final void park(int location){
System.out.println("Vehicle parking..");
}}
class Car extends Vehicle{
//#Override
void park(int location) { //error
System.out.println("Car Parking..");
}}

Categories