Java abstract method and interface - java

I have an interface HTTPSequence. I also have an abstract class AbstractHTTPFactory which in turn has an abstract method returning ArrayList<HTTPSequence>. In classes derived from AbstractHTTPFactory I want to override those methods to return ArrayList<[Class implementing HTTPSequence]>.
Is it possible ? Now compiler gives my an error suggesting that I change overriden methods signature to HTTPSequence.
// abstract class with abstract method returning ArrayList of objects implementing interface
abstract public class AbstractHTTPFactory {
abstract ArrayList<HTTPSequence> make();
}
// Specific class that returns ArrayList of objects of the class implementing HTTPSequence
public class RecipesHTTPFactory extends AbstractHTTPFactory{
public ArrayList<Recipe> make() {
}
}
// interface
public interface HTTPSequence {
}
// one of the classes implementing the above interface
public class Recipe implements HTTPSequence {
}
And the message Eclipse gives me is:
Multiple markers at this line
- The return type is incompatible with AbstractHTTPFactory.make()
- implements ....ider.AbstractHTTPFactory.make

You could write your AbstractClass method to return ArrayList<? extends Interface>, and then you do not have to change the derived class method signatures

The following design would allow you to avoid having to return a wildcarded generic type, which are of limited use to the caller:
abstract public class AbstractHTTPFactory<T extends HTTPSequence> {
abstract ArrayList<T> make();
}
public class RecipesHTTPFactory extends AbstractHTTPFactory<Recipe> {
public ArrayList<Recipe> make() { ... }
}
Now you can call new RecipesHTTPFactory().make() and get back an ArrayList<Recipe> instead of an ArrayList<? extends HTTPSequence>.
Also note that unless the caller specifically expects an ArrayList, it is better for make() to return a List<T>.

Related

Bounded type parameters: cannot access subtype methods when overriding

I'm new to using bounded types in Java, and I'm not sure if the following is a programming error because of a bad use of inheritance or a javac bug
I need to define two different type of objects: things which have to be managed and managers of that things. That's why I created an abstract class to model the common behavior of those things
public abstract class AbstractThing {
// Common method implemented
public void hello() {
System.out.println("HI, I'm AbstractThing");
}
}
and an interface to define the methods that those things' manager must implement
public interface AbstractManager {
// Operation that a things' manager must implement
public <T extends AbstractThing> void greet(T t);
}
So suppose I create two concrete things classes, one of them just inherits the abstract one:
public class Thing extends AbstractThing {
// Constructor
public Thing() {}
}
but the other one implements an own method:
public class AnotherThing extends AbstractThing {
// Constructor
public AnotherThing() {}
// Extra method which this class implements
public void goodbye() {
System.out.println("BYE, I'm AnotherThing");
}
}
But when I define a manager as follows:
public class Manager implements AbstractManager {
// Constructor method
public Manager() {}
// Implementation of the interface's method fails
#Override
public <AnotherThing extends AbstractThing>
void greet(AnotherThing t) {
// I can use this method, which AnotherThing inherits from AbstractThing
t.hello();
// But I can't use this one defined by AnotherThing
t.goodbye();
}
}
I get the error:
AnotherManager.java:15: error: cannot find symbol
t.goodbye();
^
symbol: method goodbye()
location: variable t of type AnotherThing
where AnotherThing is a type-variable:
AnotherThing extends AbstractThing declared in method <AnotherThing>greet(AnotherThing)
1 error
And I don't understand why, because it's recognizing the class as AnotherThing, but it's dealing it as AbstractThing. I've tried to cast the object as the subclass, but it doesn't work
I've also checked that it only happens when I try to access the subtype methods, because the following manager compile and works perfectly:
public class Manager implements AbstractManager {
// Constructor method
public Manager() {}
// Implementation of the method defined into the interface
#Override
public <Thing extends AbstractThing>
void greet(Thing t) {
t.hello();
}
// I can overload the method "greet" without overriding the interface
// and it works for AnotherThing
public void greet(AnotherThing t) {
t.hello();
t.goodbye();
}
}
Any idea about what's happening there?
Here's why
It's not difficult to figure out if you do something like this
public class Manager implements AbstractManager {
// Constructor method
public Manager() {}
// Implementation of the interface's method fails
#Override
public <T extends AbstractThing>
void greet(T t) {
// I can use this method, which T inherits from AbstractThing
t.hello();
// But I can't use this one because T inherits from AbstractThing which does not know this method
t.goodbye();
}
}
In other words, the word before the "extends" is not supposed to be a class name, but a generic identifier (a variable name).
In this case, since T (or wharever you call it) is AbstractThing, it does not know what goodbye() is.
Now, why your last example works?
Because you're saying that greet receives a object of type AnotherThing, not a generic type such as T.
AnotherThing in <AnotherThing extends AbstractThing> has nothing to do with the class AnotherThing. It's the name a type parameter, same as if it were called T. The reason it acts like AbstractThing is because that's all we know it is. Your method doesn't know how it's parameterized; all it knows is that it's getting a subclass of AbstractThing. This can be useful for constructs where we need to capture the type, but we don't care what subtype it is, e.g.:
<T extends AbstractThing> void copy(List<T> from, List<T> to) {
for (T t : from) {
t.hello();
to.add(t);
}
}
But if you want a specialized subclass of AbstractManager to manage AnotherThing, the type parameter should be on the class, not the method:
public interface AbstractManager<T extends AbstractThing> {
// Operation that a things' manager must implement
public void greet(T t);
}
public class AnotherManager implements AbstractManager<AnotherThing> {
#Override
public void greet(AnotherThing t) {
t.hello();
t.goodbye();
}
}

Need to understand the syntax class Builder<T extends Builder<T>>

I am following examples in "Effective Java" and came across the following code:
abstract static class Builder<T extends Builder<T>>
and its implementation:
public static class Builder extends Pizza.Builder<Builder>
Why is this declared T extends Builder<T> and not T extends Builder. Is it really needed to add the template <T>? What is the impact if I just use Builder<T extends Builder>?
It is called as "generic type". That declaration means T can be any type that is subclass of Builder<T>.
The goal of implementing Generics is finding bugs in compile-time other than in run-time. Finding bugs in compile-time can save time for debugging java program, because compile-time bugs are much easier to find and fix.
What is the impact if we just use Builder<T extends Builder>?
It transforms into raw type. And type safety goes off.
Builder<T extends Builder<T>> means that,
The class T passed in must implement the Builder interface / extend Builder class, and the generic parameter of Builder must be T itself.
I have some examples to show that actually the difference is not that big. I think the OP wants to know the difference between T extends Builder<T> and T extends Builder.
public abstract class Builder2<T extends Builder2> {
//doesn't compile either, because String is not a subtype of Builder2
static class WrongHouseBuilder extends Builder2<String> {}
//all ok
static class RawHouseBuilder extends Builder2 {}
static class HouseBuilder1 extends Builder2<RawHouseBuilder> {}
static class HouseBuilder2 extends Builder2<HouseBuilder1> {}
static class HouseBuilder3 extends Builder2<HouseBuilder2> {}}
Now with Builder<T>:
public abstract class Builder<T extends Builder<T>> {
//all ok
static class RawCarBuilder extends Builder {}
static class CarBuilder extends Builder<CarBuilder> {}
//ok as well, T doesn't have to be CarBuilder2
static class CarBuilder2 extends Builder<CarBuilder> {}
//doesn't compile because CarBuilder2 is not a subtype of Builder<CarBuilder2>
static class CarBuilder3 extends Builder<CarBuilder2> {}}
Of cause with T extends Builder<T>, you have more protection, but not that much.
UPDATE
Just to clarify, we should not use raw type. #Radiodef has provided an interesting example in the comment. And a quote from that answer to help you understand it:
In simpler terms, when a raw type is used, the constructors, instance methods and non-static fields are also erased.
Minor: It looks more natural to me to use Builder as an interface, not an abstract class. This is a sort of recursive type declaration. It is used for type safety to prevent nasty things like the following happens:
public abstract Builder<T extends Builder<T>> {
T build();
}
public class Entity extends Builder<String>{ // does not compile
#Override
public String build() {
return null;
}
}
public class Entity extends Builder<Entity>{ //ok
#Override
public Entity build() {
return null;
}
}
Anyway more naturally looking version (from my point of view) is:
public interface Buildable<T extends Buildable<T>> {
T build();
}
public final class Entity implements Buildable<Entity>{
//other methods
#Override
public Entity build() {
//implementation
}
}
I see that the question is about the <T> part in Builder<T>. Without this <T>, you simply get a raw type, and your IDE might complain.
But in my answer, I'd like to explain what's the purpose of T extends Builder<T>, because other answers do not seem to cover it (maybe you know this already).
T extends Builder<T> serves the purpose of returning appropriate Builder.this in all the Builder methods (except build() method, of course).
I usually use it with a protected abstract method like T thisInstance().
Example:
abstract class NamedBuilder<T extends NamedBuilder<T>> {
private String name;
T name(String name) {
this.name = name;
return thisInstance();
}
protected abstract T thisInstance();
}
final class MoreSpecificBuilder extends NamedBuilder<MoreSpecificBuilder> {
#Override
protected MoreSpecificBuilder thisInstance() {
return this;
}
}
Thanks to such approach, you do not have to redefine name() method in all the NamedBuilder subclasses to return the specific subclass.
Without such constraint type parameter T, you would have:
abstract class NamedBuilder {
NamedBuilder name(String name);
}
and you would need to override all such methods in subclasses like that:
final class MoreSpecificBuilder extends NamedBuilder {
#Override
MoreSpecificBuilder name(String name) {
super.name(name);
return this;
}
}
EDIT: Without the constraint extends Builder<T> on type parameter T:
abstract class NamedBuilder<T> {
// ...
}
this would work fine, although such design would be less intuitive and more error-prone.
Without such constraint, compiler would accept anything as T (e.g. String), so the constraint acts simply as a compile-time check for the implementors of NamedBuilder.

How do I parameterise in an interface and then specify generic type in implemented class

I want to have an interface as :
public interface CarManager<T extends Car> {
public T createCar(Map data);
public T saveCar(T t);
}
so that I can do:
public class FiatManager<Fiat> implements CarManger {
public Fiat createCar(Map data) {
// ...
}
// ...
}
for various cars that extend Car.
However, when I try, I get an error that I haven't implemented createCar
The exact error message is:
The class 'FiatManager' must be declared abstract or the method Car createCar(Map data)' must be implemented.
You forgot to implement the interface:
public class FiatManager implements CarManager<Fiat>
Of course, you have to make sure that Fiat extends Car.
Also, (as #Thilo correctly noted) note that FiatManager is not generic anymore, since it is already known as a one that's dealing with Fiat(s).
For just Fiats, then:
public class FiatManager implements CarManager<Fiat>
public Fiat createCar(Map data) {
// ...
}
// ...
}
For all Cars:
public class FiatManager<T extends Car> implements CarManager<T>
public T createCar(Map data) {
// ...
}
// ...
}
You need to declare your FiatManager class as:
public class FiatManager implements CarManager<Fiat>{
Then you need to implement both methods createCar and saveCar.
Of course, that is assuming you have a Fiat class extending or implementing Car.
Finally, watch out for the raw Map in your method parameters!

How to properly override an abstract method with generics in the signature

I thought I understood how to do this but I'm getting some unexpected behavior so apparently I'm missing something. Here's the problem boiled down.
Base Class:
public abstract class Base<T>
{
abstract public void foo(List<? extends T> l);
}
Derived Class:
public class Derived<T> extends Base
{
#Override
public void foo(List<? extends T> l) { return; }
}
The Base class complies fine, but when I compile the Derived class I get:
Derived.java:3: Derived is not abstract and does not override abstract method foo(java.util.List) in Base
public class Derived extends Base
^
Derived.java:5: method does not override or implement a method from a supertype
#Override
^
2 errors
The generics of the parameter List<? extends T> appears to be the cause of the problem. If I replace that part in both signatures with the basic type int it comples fine.
Can anybody tell me what's going on here?
You should do
public class Derived<T> extends Base<T>
You need to specify <T> for Base otherwise you will have to override method by simply declaring List i.e.without generics
You can also pass the type parameter in your class declaration like this:
public class Derived extends Base<SomeConcreteType> {
#Override
public void foo(List<SomeConcreteType> l) {
// ...
}
}
if you no longer need the generic part of the abstract class because you are going to use a concrete type in your derived class. Otherwise you have to do what the other answer stated.

Java generics in an interface

I have run into a problem with generics in Java and I can't find a solution or example online of someone using generics in a similar fashion. I have a set of methods that are in the same request/response structure. For example, a user populates fields in the Request object, passes the object to a helper method, and they are returned a Response object. All of my request objects extend from a common Request super class (and similarly, Response objects from a Response super class). I would like my helper classes to also have a consistent structure so I have used an interface. Here is some code to illustrate...
Request super class:
public class SuperRequest {
// ...
}
Example Request subclass:
public class SubRequest extends SuperRequest {
// ...
}
Response super class:
public class SuperResponse {
// ...
}
Example response subclass:
public class SubResponse extends SuperResponse{
// ...
}
The interface:
public interface SomeInterface {
public <T extends SuperRequest, U extends SuperResponse> U someMethod(T request);
}
As you can see from the interface, I want to pass an object that is a child of SuperRequest and I want to return an object that is a child of SuperResponse. Here is my implementation:
public class SomeImplementation implements SomeInterface {
#Override
public SubResponse someMethod(SubRequest request) {
return null;
}
}
In Eclipse, I get compilation errors because the compiler tells me I have unimplemented methods and the #Override notation "does not override a supertype method".
Can anyone help me here? Is my syntax incorrect or is my understanding of generics a little off? Any help is greatly appreciated!
Try changing your interface and implementation to:
interface SomeInterface<T extends SuperRequest, U extends SuperResponse> {
public U someMethod(T request);
}
class SomeImplementation implements SomeInterface<SubRequest, SubResponse> {
#Override
public SubResponse someMethod(SubRequest request) {
return null;
}
}
As it stands, the implementation of SomeInterface must implement the parameterized method, i.e.:
public <T extends SuperRequest, U extends SuperResponse> U someMethod(T request);
It can't choose a particular Subclass to substitute for T and U.
The interface itself must be generic SomeInterface<T extends SuperRequest, U extends SuperResponse> and the subclass can then choose concrete implementations for T and U.
You have to declare the types as well when you implement the interface. Try this:
public class SomeImplementation implements SomeInterface<SubRequest,SubResponse> {
#Override
public SubResponse someMethod(SubRequest request) {
return null;
}
}

Categories

Resources