Reference Object Through Its Implemented Generalized Interface [duplicate] - java

This question already has answers here:
Java generic interfaces with typesafe implementations
(2 answers)
Closed 8 years ago.
I have a converter interface that looks something like this:
public interface MyTypeConverter<T>
{
public MyObject toMyObject(T obj);
public T fromMyObject(MyObject mo);
}
I also have an implementation of that interface:
public class ABCTypeConverter implements MyTypeConverter<ABCObject>
{
public MyObject toMyObject(ABCObject obj)
{
...do conversion...
}
public ABCObject fromMyObject(MyObject mo)
{
...do conversion...
}
}
And a factory that evaluates the objects type, and returns an appropriate converter implementation:
public class MyTypeConverterFactory
{
public static MyTypeConverter<?> create(Object source)
{
if ( source instanceof ABCObject )
return new ABCTypeConverter();
...and so on...
}
}
Now the problem I am having is in referencing the Factory's returned converter instance by using the interface:
MyTypeConverter<?> converter = MyTypeConverterFactory.create(someObject);
MyObject mo = converter.toMyObject(someObject);
The last line gives me the following compile-time error:
The method toMyObject(capture#3-of ?) in the type MyTypeConverter<capture#3-of ?>
is not applicable for the arguments (ABCObject)
So how could I reference the converter in a generic fashion?
EDIT
The core of my question is: How do I call a method on an interface reference without first casting to the underlying concrete type? And if I can't, then what is the point of creating a generic interface to begin with? I.E., How do I do this (regardless of how I get the reference):
MyTypeConverter<?> converter = MyTypeConverterFactory.create(someObject);
MyObject mo = converter.toMyObject(someObject);
Without first casting "converter" to its underlying concrete type?

This is a total anti-pattern approach to the FactoryMethod Pattern:
if ( source instanceof ABCObject )
return new ABCTypeConverter();
...and so on...
Don't do that it will never scale and will never be maintainable.
What is wrong with:
TypeConverter<ABCObject> tc = new TypeConverter<ABCObject>();
That is how every sane framework that implements something like this works.
For example:
com.google.common.base.Converter
Look at the how Jackson does it for JSON Serializer/Deserializers as well.
There is a way with Guava to get an instance of a type T
Class<T> klass = (Class<T>) new TypeToken<T>(getClass()) {}.getRawType();
Then you can do klass.newInstance(); but this is hacky was well.

You can try with Polymorphism as well instead of making it Generic.
Just return the interface reference instead of actual object reference from factory's create() method. At run-time the actual object decide what method should be called based on overridden method logic.
In below sample code I have created an interface MyTypeConverterObject that is implemented by all the classes that are part of MyTypeConverter interface.
Now simply return MyTypeConverterObject from factory's create() method.
Sample code:
interface MyTypeConverterObject {}
class ABCObject implements MyTypeConverterObject {}
class XYZObject implements MyTypeConverterObject {}
class MyObject {}
interface MyTypeConverter {
public MyObject toMyObject(MyTypeConverterObject obj);
public MyTypeConverterObject fromMyObject(MyObject mo);
}
class ABCTypeConverter implements MyTypeConverter {
public MyObject toMyObject(MyTypeConverterObject obj) {
return new MyObject();
}
public MyTypeConverterObject fromMyObject(MyObject mo) {
return new ABCObject();
}
}
class MyTypeConverterFactory {
public static MyTypeConverter create(Object source) {
if (source instanceof ABCObject) {
return new ABCTypeConverter();
}
return ...;
}
}
A Factory method should return product of same type i.e. product that implements same interface.
For example: A car factory can return cars of different type but can't produce bike.
If you need to return different type of products then use Abstract factory.

Related

Java generic interface calling with abstract parameter

I know there's many similar question but I had no luck finding a nice and clean solution if it's possible at all.
I'm implementing a generic interface with subclasses of an abstract type. Problem is that when I'm calling them I either must do type cast in a switch/case or cast type in every method inside interface implementations and I can't figure out a nice and clean approach... I'll better just write down a short example.
// An abstract type with 2 implementations...
public abstract class ObjTypeAbstract {}
public class ObjType extends ObjTypeAbstract {}
public class ScriptType extends ObjTypeAbstract {}
Now the processor for both types with an interface
interface ProcessorInterface<T extends ObjTypeAbstract> {
public void abcMethod(T obj);
}
public class ObjProcessor implements ProcessorInterface<ObjType> {
public void abcMethod(ObjType obj) {}
}
public class ScriptProcessor implements ProcessorInterface<ScriptType> {
public void abcMethod(ScriptType obj) {}
}
What I'm struggling with is a way of calling those processors based on ObjAbstractType. I have a single class that servers as middleware?? or how should I call it.:
Idea was to simple get the right processor via a single switch/case:
public class Processor {
private ProcessorInterface objProcessor = new ObjProcessor();
private ProcessorInterface scriptProcessor = new ScriptProcessor();
public methodAbc(ObjAbstractType obj) {
getProcessor(obj).abcMethod(obj);
}
private ProcessorInterface getProcessor(ObjAbstractType obj) {
if (obj instanceof ObjType) {
return objectProcessor;
} else if (obj instanceof ScriptType) {
return scriptProcessor;
}
return nullProcessor;
}
}
This is what I'd like to have, it also takes care of type casting of objAbstract to actual type for abcMethod, problem is that it results in RawType warning which won't break the code, but I'd like to get rid of it.
And thats where I'm stuck... because if I cast processors to specific type like this:
private ProcessorInterface<ObjType> objProcessor = new ObjProcessor();
private ProcessorInterface<ScriptType> scriptProcessor = new ScriptProcessor();
I won't be able to return an abstract one from getProcessor method so I would have to implement those interfaces with an ObjAbstractType with all it's method and have type casting in all methods of every processor like:
public class ScriptProcessor implements ProcessorInterface<ObjAbstractType> {
public void abcMethod(ObjAbstractType obj) {
ScriptType scr = (ScriptType) obj;
}
}
The other solution might be having a switch/case inside Processor middleware class and cast ObjAbstractType in it, but I'd have to write that switch inside abcMethod and all others or from getProcessor method returns both the Processor and casted ObjType... so I'd have to return some dto containing both. :/
Do you have any ideas / patterns that might help me to get rid of RawType call warning without extending the code with more switch/case or type casts?
Wish you a nice day and I'll be glad for any discussion, David.
You need a way to store the mapping between a ObjTypeAbstract class and a ProcessorInterface instance.
You could use a Map that associates ObjTypeAbstracts (as key) to ProcessorInterfaces (as value).
About the raw type issue, you could use ProcessorInterface<? extends ObjTypeAbstract> for the declared variable but you will still need to perform a unsafe cast to ProcessorInterface<ObjTypeAbstract> to be able to invoke ProcessorInterface.abcMethod() with as parameter a ObjTypeAbstract declared type.
This cast is unavoidable with your actual design.
It could give something like :
public class Processor {
private Map<Class<? extends ObjTypeAbstract>, ProcessorInterface<? extends ObjTypeAbstract >> map = new HashMap<>();
public Processor(){
map.put(ObjType.class, new ObjProcessor());
map.put(ScriptType.class, new ScriptProcessor());
}
public void methodAbc(ObjTypeAbstract obj) {
#SuppressWarnings("unchecked")
ProcessorInterface<ObjTypeAbstract> processorInterface = (ProcessorInterface<ObjTypeAbstract>) map.get(obj.getClass());
processorInterface.abcMethod(obj);
}
}
I don't think there is a substantially more elegant way to get around some form of instanceof logic. However, there should not be need for casting, if you add some types to getProcessor.
public <T extends ObjTypeAbstract> ProcessorInterface<T> getProcessor(Class<T> theClass) {
if (theClass.isAssignableFrom(ObjType.class)) {
return objProcessor;
} else if (theClass.isAssignableFrom(ScriptType.class)) {
return scriptProcessor;
}
return null;
}
This can then be called like this:
ProcessorInterface<ScriptType> scriptProcessor = new Processor().getProcessor(ScriptType.class);
ProcessorInterface<ObjType> objProcessor = new Processor().getProcessor(ObjType.class);

Avoiding instanceof in factory method

I'm looking for an improved solution to the following problem. I have an object, which is passed to a factory; the factory will inspect the object type, create another type, which it populates with data from the incoming object, and returns the new one.
...
public MyAbstractClass create(MyObject a) {
if (a instanceof A) {
A obj = (A) a;
return new MyAbstractClass_1 (obj.getField(), factoryField);
}
else if (a instanceof B) {
B obj = (B) a;
return new MyAbstractClass_2 (obj.getSomething(), obj.getSomethingElse(), factoryField);
}
}
Instances of the return type are treated generically afterwords. Going forward I need to support more types and if possible I'd like to avoid an instanceof solution. How can I improve this?
Can you add the create method to MyObject instead? That way you won't need instance of anymore because each instance of MyObject knows how to 'create'. You won't have a factory anymore though :(
It would look something like (assuming MyObject is an interface. if it's a class, then just extend instead):
interface MyObject {
...
public MyAbstractClass create(MyObject a);
...
}
public class A implements MyObject {
...
public MyAbstractClass create(MyObject a) {
return new MyAbstractClass_1 (obj.getField(), factoryField);
}
...
}
public class B implements MyObject {
...
public MyAbstractClass create(MyObject a) {
return new MyAbstractClass_2 (
obj.getSomething(),
obj.getSomethingElse(),
factoryField);
}
...
}
The bodies of your if statements should be virtual or abstract members on MyObject.
abstract class MyObject {
public abstract MyAbstractClass create();
}
class A extends MyObject {
#Override
public MyAbstractClass create(Object factoryField) {
return new MyAbstractClass_1 (this.getField(), factoryField);
}
}
class B extends MyObject {
#Override
public MyAbstractClass create(Object factoryField) {
return new MyAbstractClass_2 (this.getSomething(), this.getSomethingElse(), factoryField);
}
}
Generally, when you see yourself checking the type of an object to do something different depending on the concrete type, that likely means that you should be using polymorphism and the code should be going into the concrete types themselves.
Updated that the MyObject data should be coming from the current instance and not passed as a parameter, as you pointed out. Only issue is that I'm not sure where you'd put factoryField now. You could pass it as a parameter as above, and since these are virtual members you could still have a factory as well:
class SomeFactory {
private Object factoryField;
public SomeFactory(Object factoryField) {
this.factoryField = factoryField;
}
public MyAbstractClass create(MyObject a) {
return a.create(factoryField);
}
}

Use Method of generic type

I am currently writing an XML converter for a supply chain project. We use Requests and Orders.
The converter has multiple method that currently do same but are separately implements for requests and orders.
I have therefore created an abstract class to improve maintainability of the code and used a generic type:
public abstract class AbstractConverter<T extends BusinessObject>
Then I have the specific implementations for the actual converters
public class OrderConverter extends AbstractConverter<Order>
public class RequestConverter extends AbstractConverter<Request>
As I said, I have several methods in the two specific classes that basically do the same, so I naturally want them in the abstract class. I have now added the following method to the abstract class:
protected Comment createComment(T obj) {
String remark;
if (obj instanceof Order) {
remark = ((Order) obj).getRemark();
} else if (obj instanceof Request) {
remark = ((Request) obj).getRequestRemark();
} else {
throw new IllegalArgumentException("This method does not support objects of the type " + obj.getClass().toString());
}
return new Comment(remark);
}
My question now is: is this the way to go or is there a more elegant way to use generics in this context?
I need this solved but I also want to use good style.
The natural object oriented solution is to make createComment an abstract method
protected abstract Comment createComment(T obj);
and let the subclasses implement it:
public class OrderConverter extends AbstractConverter<Order> {
protected Comment createComment(Order order) {
return new Comment(order.getRemark());
}
}
public class RequestConverter extends AbstractConverter<Request> {
protected Comment createComment(Request request) {
return new Comment(request.getRequestRemark());
}
}
I'd suggest extracting the getRemark method to an interface which both Request and Order implements.
That way you can simply check if the incoming generic object is an instance of the interface.
protected Comment createComment(T obj) {
if (obj instanceof Remarkable) {
return new Comment(((Remarkable) obj).getRemark());
}
throw new IllegalArgumentException("This method does not support objects of the type " + obj.getClass().toString());
}

How do I create an instance of a parameterized interface [duplicate]

This question already has answers here:
Create instance of generic type in Java?
(29 answers)
Closed 7 years ago.
I have this code:
ObjProcessor processor = getProcessor();
MyClass myObj = getObjToProcess();// MyClass extends PersistentObj
and classes:
public class ObjProcessor {
public <OP extends PersistentObj) void process(Class<OP> objClazz, OP object, Modifier<OP> modifier) {
...
}
}
public interface Modifier<T> {
void modify(T obj);
}
I am stuck. How do I create an instance of the Modifier to be able to invoke:
processor.process(myObj.getClass(), myObj, ???);
After Ron C's comment, I created this Modifier:
Modifier<MyClass> mod = new Modifier<MyClass>() {
#Override
public void modify(MyClass obj) {
// empty
}
};
proc.process(myObj.getClass(), myObj, mod); // compilation error!
Eclipse gave this error:
The method process(Class<OP>, OP, Modifier<OP>) in the type ObjProcessor is not applicable for the arguments (Class< capture#1-of ? extends MyClass>, MyClass, Modifier<MyClass>)
You can create an anonymous inner class as an instance of the Modifier interface:
processor.process(myObj.getClass(), myObj, new Modifier<MyClass>() {
#Override
public void modify(MyClass obj) {
//Add implementation here
}
});
If you're using java 8, you can also use lambada expressions. Because your interface is considered as a Functional Interface (interface with only one method), you can use lambada expression instead of creating anonymous class:
processor.process(myObj.getClass(), myObj, obj -> {
//Add implementation here
});
For the second problem, the solution is to change the declaration of process to:
public <OP extends ObjProcessor> void process(Class<? extends OP> objClazz, OP object, Modifier<OP> modifier) {
}
I've replaced Class<OP> with Class<? extends OP>. The older decleration only works with: MyClass.class, but not with: instanceOfMyClass.getClass().
The reason for this is that the Class<OP> type argument can't accept Class<ClassExtendsOP> as an argument, it's only allow one class.
If your'e using MyClass as OP,
when you're using MyClass.class, you're always getting Class<MyClass> object. But when you're using instanceOfMyClass.getClass(), you can get Class<ClassExtendsMyClass>, which not match the argument type.

Java - Overriding return type of extended interface when return type uses generics for own method parameter types

i've stumbled upon a curiosity in the java inheritance, and I wanted you to ask for better ideas on that:
Assume two interfaces A and A1
Interface A1 extends A
Interface A has a method which returns a generic type.
The generic type would be like GenericType<T>.
A basic idea is now to change this generic return type from
GenericType<Object> in Interface A into
GenericType<String> in Interface A1
Well seems to be easy at first (bad things will come later on)
We declare Interface A like
public interface InterfaceA {
public GenericType<? extends Object> getAGenericType();
}
and Interface A1 like
public interface InterfaceA1 extends InterfaceA
{
#Override
public GenericType<String> getAGenericType();
}
As you see we are forced to write GenericType<? extends Object> in Interface A itself to allow overriding it with generic based "subclasses".
(In fact the generic parameter of the generictype is subclassed not the generic type itself)
Now assume the GenericType has its own method looking like:
public interface GenericType<D>
{
public void doSomethingWith( D something );
}
Now trying to instantiate A1 works great.
Rather trying to instantiate A will suck. To see why look at this "use the interface" class:
public class LookAtTheInstance
{
#SuppressWarnings("null")
public static void method()
{
InterfaceA a = null;
InterfaceA1 a1 = null;
GenericType<String> aGenericType = a1.getAGenericType();
GenericType<? extends Object> aGenericType2 = a.getAGenericType();
Object something = null;
aGenericType2.doSomethingWith( something );
}
}
You ask: "And now?"
It does not work on the last lines. In fact the parameter "something" is not even from type "Object" it is from Type "? extends Object". So you cannot pass the declared "Object" type. You can't pass anything at all.
So you end up declaring nice interfaces which, as it turns out, cannot be instantiated right.
Do you have ideas how to model such a use case, where the subclasses will have to override the return type, while the return type is a generics?
Or how would you go around such a model case?
Or am I just missing a simple point in the generic declaration and my example is possible this way?
----------- (1) edit due to answers -----------
A very good basic idea is making the interface A more abstract! I had exactly the same idea first, but... (this has to come)
Assume doing this:
We introduce a new interface AGeneric
public interface InterfaceAGeneric<T>{
public GenericType<T> getAGenericType();
}
Now we will have to extend A and A1 from this new interface:
public interface InterfaceA extends InterfaceAGeneric<Object>{}
public interface InterfaceA1 extends InterfaceAGeneric<String>{}
That works fine, althought it breaks the path of the original inheritance.
If we want A1 still be extendable from A, we have to change A1 to
public interface InterfaceA1 extends InterfaceA, InterfaceAGeneric<String>{}
and there a problem is again. This does not work, since we extend indirectly the same interface with different generic types. This is unfortunately not allowed.
You see the problem?
-
And to point to another circumstance:
If you cast the GenericType<? extends Object> to GenericType<Object> it obviously works.
Example:
public class LookAtTheInstance
{
public static void main( String[] args )
{
InterfaceA a = new InterfaceA()
{
#Override
public GenericType<? extends Object> getAGenericType()
{
return new GenericType<Object>()
{
#Override
public void doSomethingWith( Object something )
{
System.out.println( something );
}
};
}
};
;
#SuppressWarnings("unchecked")
GenericType<Object> aGenericType2 = (GenericType<Object>) a.getAGenericType();
Object something = "test";
aGenericType2.doSomethingWith( something );
}
}
So it seems for me that the resolving of the parameter type of the method
public interface GenericType<D extends Object>
{
public void doSomethingWith( D something );
}
is wrong.
If D is unified with "? extends Object" why the parameter type is not forced to be "Object"?
Wouldnt this make more sence?
A basic idea is now to change this generic return type from GenericType in Interface A into GenericType in Interface A1
This is not possible, because Java Generics are invariant. [1]
As you found out, you cannot have an interface declaring a method that returns GenericType<Object> and in a sub interface override the method to return GenericType<String>: The latter return type is not a subtype of the former. And for good reason!
You tried to
extend indirectly the same interface with different generic types. This is unfortunately not allowed.
There is no way this could possibly work: E.g. what should be the type of E in public E set(int index, E element) in a class that implemented both List<String> and List<Object>? Your subclassed interface would have to produce a similar hybrid: The return value of getAGenericType in the sub interface would have to implement both the GenericType<String> and the GenericType<Object> interface. And as we saw, this is impossible.
The compiler does not know what you are going to do with the type parameter in GenericType (although it theoretically could find out, it doesn't). If you had a variable of type GenericType<String> and assigned a GenericType<Object> to it, you may very well end up putting a Long instance where a String is expected, and get a ClassCastException where you won't expect one.
In the doSomethingWith method of your variable GenericType<? extends Object> aGenericType2 you can pass one thing: null. null is the only object reference that has a subtype of ? extends Object. The lower bound type of ? extends Object is the null type, which cannot be expressed in Java, and only implicitly exists as the type of the null reference.
[1] http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29#Java
I don't know if this is what you are expecting, but you can declare your interface something like:
public interface Interface <K extends Object> { ... }
While your class might look like:
public class InterfaceImpl implements Interface<String> { ... }
#Override annotation:
When overriding a method, you might
want to use the #Override annotation
that instructs the compiler that you
intend to override a method in the
superclass. If, for some reason, the
compiler detects that the method does
not exist in one of the superclasses,
it will generate an error.
With this annotation you cannot change return type of function.
If you want to override return type, just make interface A more abstract, add generic to this interface:
public interface InterfaceA<T> {
public GenericType<T> getAGenericType();
}
Sample about overriding a generic method in a generic class.
The trouble is that InterfaceA doesn't know what type it's holding. If you get InterfaceA to take a generic argument then you could do this:
public interface InterfaceA<T>
{
public GenericType<T> getAGenericType();
}
public interface InterfaceA1 extends InterfaceA<String>
{
#Override
public GenericType<String> getAGenericType();
}
public class LookAtTheInstance
{
#SuppressWarnings("null")
public static void method()
{
InterfaceA<String> a = null;
InterfaceA1 a1 = null;
GenericType<String> aGenericType = a1.getAGenericType();
GenericType<String> aGenericType2 = a.getAGenericType();
String something = null;
aGenericType2.doSomethingWith( something );
}
}
I'm several years late to the party, but I found this page while searching for a related question and none of the answers really hit on the central issue, which I think is worth clarifying. Let's look at a slightly-more-fleshed-out example:
interface GenericType<D> {
D getAValue();
void doSomethingWith(D value);
}
class StringType implements GenericType<String> {
#Override
public String getAValue() {
return "Hello World";
}
#Override
public void doSomethingWith(final String value) {
System.out.println(value.length());
}
}
interface InterfaceA {
GenericType<? extends Object> getAGenericType();
}
interface InterfaceA1 extends InterfaceA {
#Override
GenericType<String> getAGenericType();
}
class AnActualA1 implements InterfaceA1 {
#Override
public GenericType<String> getAGenericType() {
return new StringType();
}
}
class LookAtTheInstance {
public static void method() {
InterfaceA1 a1 = new AnActualA1();
// 'g1' is a StringType, which implements GenericType<String>; yay!
GenericType<String> g1 = a1.getAGenericType();
// Everything here is fine.
String value = g1.getAValue();
g1.doSomethingWith("Hello World");
// But if we upcast to InterfaceA???
InterfaceA a = (InterfaceA) a1;
// Note: a.getAGenericType() still returns a new StringType instance,
// which is-a GenericType<? extends Object>.
GenricType<? extends Object> g = a.getAGenericType();
// StringType.getAValue() returns a String, which is-an Object; yay!
Object object = g.getAValue();
// StringType.doSomethingWith() method requires a String as the parameter,
// so it is ILLEGAL for us to pass it anything that cannot be cast to a
// String. Java (correctly) prevents you from doing so.
g.doSomethingWith(new Object()); // Compiler error!
}
}
Conceptually, GenericType is NOT a GenericType, since a GenericType can only doSomethingWith() Strings, while a GenericType needs to be able to doSomethingWith() any object. GenericType is a compromise which the compiler allows you to use as a "base class" for any GenericType where D is-an Object, but only allows you to use a reference of that type to call methods that are type-safe for any possible runtime value of '?' (such as getAValue(), whose return value can always be safely cast to an Object since D is-an Object regardless of runtime type).
It's hard to tell what (if anything) the original poster was actually trying to model with this code, and in particular how much of the generic-ness of GenericType was really needed, but perhaps the inheritance should have gone the other way around?
/**
* I can do something with instances of one particular type and one particular
* type only.
*/
interface GenericType<D> {
void doSomethingWith(D value);
}
/**
* I can do something with instances of any type: I am-a GenericType<String>
* because I can totally do something with a String (or any other kind of
* Object).
*/
interface NonGenericType extends GenericType<Object>, GenericType<String> {
#Override
void doSomethingWith(Object value);
}
interface StringHandlerFactory { // nee InterfaceA1
GenericType<String> getAGenericType();
}
/**
* I extend StringHandlerFactory by returning a NonGenericType (which is-a
* GenericType<String>, satisfying the interface contract, but also so much
* more).
*/
interface ObjectHandlerFactory extends StringHandlerFactory { // nee InterfaceA
#Override
NonGenericType getAGenericType();
}
The downside being that there's no good way to express to the java compiler that NonGenericType extends GenericType, even though conceptually it could in this case, since GenericType never uses D as a return value. You have to manually specify each GenericType that you want it to extend. :(
So you end up declaring nice interfaces which, as it turns out, cannot be instantiated right.
I think that the purpose of InterfaceA is not to be instantiated at all, because one of its dependable classes are generic. That's what you meant declaring:
public GenericType<? extends Object> getAGenericType()

Categories

Resources