I have a set of classes that all need to be acted on in some (individual) way.
Ordinarily I'd just create a DoSomethingInterface with a single doSomething() method and have each class implement that method in a way that suits each class' needs. However, I cannot do that in this case as the class definitions are unmodifyable (auto-generated)
So, I reckon I need to create a set of different classes that each take one of the autogenerated classes and performs the operation on them. So, say I have 2 autogenerated classes, Class1 and Class2, I will first define a common Operator interface:
public interface Operator <TYPE>{
public void doSomething(TYPE type);
}
and then implement one of these per class
public class Class1Operator implements Operator<Class1>{
public void doSomething(Class1 type){
...
...
}
}
and
public class Class2Operator implements Operator<Class2>{
public void doSomething(Class2 type){
...
...
}
}
Ok, so far so good. Now, given that I have an object of type Class1, is there any way of getting its operator without resorting to:
public Operator getOperator(Object obj){
if(obj instanceof Class1){
return new Class1Operator();
}else if(obj instanceof Class2{
return new Class2Operator();
}
return null;
}
Which kinda seems like bad practice to me...
The only other way I can think of is by creating a map of operators to class names like so:
Map<Class, Operator> allOperators = new HashMap<Class, Operator>();
allOperators.put(Class1.class, new Class1Operator());
allOperators.put(Class2.class, new Class2Operator());
and then return the operator using:
public Operator getOperator(Object obj){
return allOperators.get(obj);
}
But this doesn't seem right (I'm not sure, are there any issues with keying an object off its class....)
Any input as to whether either of these approaches is 'correct'? or is there a more elegant solution??
Thanks
What you've implemented (the map-by-class approach) is one of the alternatives to the GoF Visitor pattern I talk about when I teach patterns. It's efficient and extendable, even at runtime. Much better than the if/else if/else hardwired approach.
The only issue with keying off the class is if the actual instances implement subtypes rather than the class type you mention; then the lookup map won't work.
If you need subtypes to be recognized, I'd recommend Aaron's approach (walk up the superclass chain), but you may also want to look at implemented interfaces as well. If you just need "exact class match", keep your getOperator simple.
Note that you have a bug in getOperator -- it should look as follows:
public Operator getOperator(Object obj){
return allOperators.get(obj.getClass());
}
One more thing... Hide your map inside another class and manage it as follows:
private Map<Class<?>, Operator<?>> map = new HashMap<Class<?>, Operator<?>>();
public <T> void register(Class<T> clazz, Operator<T> operator) {
map.put(clazz, operator);
}
This prevents anyone from registering an operator that won't work against the class it's keyed against. (You might want to use Operator as the parameter to allow an operator that's written against a superclass, but that's might not be needed)
One of the issues with building a map is that it will not support subclasses unless you register them specifically or extend your get function to look up super classes specifically.
That is to say if B inherits from A and you've registered an operator with A.class. Fetching an operator with B.class will fail, unless you change your getOperator to something like:
public Operator getOperator(Object obj){
Class<?> current = obj.getClass();
Operator op;
while((op = allOperators.get(current)) == null){
current = current.getSuperclass();
if(current == null){
/*
* We've walked all the way up the inheritance hierarcy
* and haven't found a handler.
*/
return null;
}
}
return op;
}
Once you've got a reasonable getOperator implementation, mapping classes to operators seems like a reasonable approach.
You can us Class.isAssignableFrom to get around the sub-typing issue. I use this all the time and while it is not "visitor" elegant it is quite fine in practice.
Would it be possible to create your own class that extends the generated class and then have your class implement the interface?
Have you considered this:
public Interface Operator {
public void doSomething();
}
public class Class1Operator extends Class1 implements Operator {
...
}
public class Class2Operator extends Class2 implements Operator {
...
}
But with reference to your second question of getting an operator to an object without really needing to do the "instanceof" mojo (I guess that's what is looking unclean):
I would suggest that if you can't modify your classes to your exact needs, write a wrapper around them:
public Interface Operator<T> {
public void doSomething(T obj);
}
public Interface WrappedObject<T> {
public Operator<T> getOperator();
}
public class WrappedClass1 extends Class1 implements WrappedObject<Class1> {
...
}
public class WrappedClass2 extends Class2 implements WrappedObject<Class2> {
...
}
public class Class1Operator implements Operator<Class1> {
...
}
public class Class2Operator implements Operator<Class2> {
...
}
Would that suffice your needs?
Its always a good practice to write wrappers around classes that don't match your needs perfectly, and can't be controlled by you. It helps you keep your code healthy even if these wild classes change.
Cheers,
jrh.
I'm going to say it's not possible to do just using the interface itself, based on the way Java handles generics.
In Java, generics are erased at compile time and replaced with casts.
I haven't actually checked how it works internally, but at a guess, your interface turns into this:
public interface Operator {
public void doSomething(Object type);
}
and where it's called, into this:
public class Class1Operator implements Operator{
public void doSomething(Object type){
Class1 oType = (Class1) type;
...
...
}
}
This still isn't exactly right as type will be cast after it's returned as well, plus Java bytecode doesn't actually look like Java, but you might get the general idea.
The instanceof and Map methods should work, even if they are a bit messy.
Related
How can i make an interface in java with a function that accepts a parameter of the type that extends the interface?
For example take the interface ISelfComparable
if class A extends it then i would expect it to implement
bool compareTo(A other)
but if class B extends it then i would expect it to implement
bool compareTo(B other)
I know i can use a generic interface but it seems incorrect because it doesn't make any sense for A to extend ISelfComparable<B>
If this is impossible, what is the best practice in this kind of situation?
The usual solution is self-bounded generics, as seen in the Enum class.
interface Example<T extends Example<T>> {
void foo(T t);
}
public class ExampleImpl implements Example<ExampleImpl> {
#Override
public void foo(ExampleImpl example) {
}
}
How it works is a bit dizzying, but is explained very well here for example. There is also a very good answer on the subject here.
Note that it isn't foolproof, as it allows this:
public class ExampleImpl2 extends Example<ExampleImpl {
#Override
public void foo(ExampleImpl example) {
}
}
But in practice the self-bounded idiom is used to express exactly the sort of thing you're after.
If you really, really, really need the parameter object to always be the exact same class as this, you have to do a runtime check. (It also raises the question of why you need this, but that would take us way off topic.)
Have a look at the class java.lang.Comparable: it has an argument with the type of the objects that can be used int compareTo.
By analogy:
public interface ISelfComparable<T extends ISelfComparable<T>> {
boolean compareTo(T other);
}
There is a way to check the type of parameter but only in runtime. For example you can implement type checking in default method:
interface ISelfComparable {
default boolean compareTo(ISelfComparable param) {
if (this.getClass() != param.getClass()) {
throw new IllegalArgumentException();
}
...
}
}
Then each implementation of this interface should look like this:
class A implements ISelfComparable {
#Override
public boolean compareTo(ISelfComparable param) {
ISelfComparable.super.compareTo(param);
...
}
}
In this case if you call new A().compareTo(new B()); then java.lang.IllegalArgumentException will be thrown
I am getting this name clash error and i don't know how should i solve the problem.
I have two classes and i am using overloaded method "createSensors". To simplify here is the code that generates the problem:
public abstract class ClassA {
public static List<Sensor> createSensors(Collection<? extends ClassA> list) {
List<Sensor> sensors = new ArrayList<Sensor>();
for (ClassA s : list) {
sensors.add(s.getSensor());
}
return sensors;
}
}
public abstract class ClassB extends ClassA {
public static List<Sensor> createSensors(Collection<? extends ClassB> list) {
List<Sensor> sensors = new ArrayList<Sensor>();
for (ClassB s : list) {
sensors.add(s.getSensor());
}
return sensors;
}
}
General answer :
Apart from the problem of the same implementation here, the core of the problem is that, somewhat barbaric, "method A and Method B have the same erasure".
What makes it a complicated question is that we generally don't (at least I did not this very morning) know a lot about "Type Erasure".
To make it short :
Parametric types perform type check at compile time (to ensure type correctness) but forget their type parameters at runtime (to avoid the generation of underlying methods).
This sounds at the same time simple and puzzling.
Best way to understand it is to refer to the following literature :
What is a reifiable type ?
How and under what conditions is erasure performed ?
Have you any idea/examples about what it could imply in my coding life ?
Well that's odd and I don't really like it but I'm curious why they did that ...
Hope that'll help you as much as it helped me.
Specific answer :
In your case
public abstract class ClassA {
public static List<Sensor> createSensors(Collection<? extends ClassA> list) {
//do stuff
}
}
public abstract class ClassB extends ClassA {
public static List<Sensor> createSensors(Collection<? extends ClassB> list) {
//do other stuff
}
}
will be "transformed" by javac to
public abstract class ClassA {
public static List createSensors(Collection list) {
//do stuff
}
}
public abstract class ClassB extends ClassA {
public static List createSensors(Collection list) {
//do other stuff
}
}
where one clearly can't override the other (not the same type parameter) but end up being exactly the same at runtime (no way for your program to choose which one to use).
Enough of this problem, how to solve it ?
You may proceed with one of the following approach :
Use different names : createASensors and createBSensors
this approach is the most obvious but would seem a little less elegant.
Add a parameter : createSensors(Collection<? extends ClassA> list, ClassA typeDefiner)
this approach can seem barbaric but is a little less elegant but is the one used in java.util.List for the method <T> T[] toArray(T[] a).
The general solution is to use different names. These methods could be in classes without an inheritance relationship as these are not instance methods.
As pointed out, the method implementation in the question are the same (typo excepted).
(This issue with overloading is often confused with erasure of runtime types. Overloading is a link-time rather than a dynamic issue, so could be easily fixed in the language. It's just not a particularly useful change, and not a good idea to encourage overloading.)
Check the project setting and compiler version of the project. Right click on project --> Properties --> Java Compiler. Make sure compliance setting are up to date. I had this problem when compliance settings were set to 1.4 instead 1.6
In my project I see the interface like this. All the model extend the interface. I am wondering what is the use ?
public interface IModel {
<T> T modelTo(Class<T> clazz);
}
public interface IPerson extends IModel {
public String getFirstName();
public void setFirstName(String firstName);
public String getMiddleName();
public void setMiddleName(String middleName);
}
Then in some places in the code I see like
#Override
public void modelJoin(IModel parent, IModel sample) {
//Some code
IPerson sample= sample.modelTo(IPerson.class);
IPerson person = parent.modelTo(IPerson.class);
//Some code
}
Can you explain me the insight of it ?
It looks like the use of the Adapter pattern. The idea is to create a "view" of a class given another class, or adapt one type of class to act as another.
A simple real world example can be that of electrical sockets. In different countries different types of sockets are used. So you use adapters to plug in your phone into an electrical socket it normally doesn't "recognize".
This can of course be modelled using object oriented programming and the adapter pattern as well. Using your IModel interface but naming it IAdaptable it could be used like this.
public interface IAdaptable {
<T> T adaptAs(Class<T> clazz);
}
public interface IChargeAmerican { void chargePhoneInAmerica(); }
public interface IChargeEurope { void chargePhoneInEurope(); }
public class EuropeanSocket implements IAdaptable, IChargeEurope {
public <T> T adaptAs(Class<T> clazz) {
if (clazz.equals(IChargeAmerican.class)) {
return new EuropeanSocketToAmericanSocketAdapter(this);
}
throw new RuntimeException("unknown");
}
public void chargePhoneInEurope() {
;
}
}
public class AmericanSocket implements IChargeAmerican {
public void chargePhoneInAmerica() {
;
}
}
public class EuropeanSocketToAmericanSocketAdapter implements IChargeAmerican {
private EuropeanSocket socket;
public EuropeanSocketToAmericanSocketAdapter(EuropeanSocket socket) {
this.socket = socket;
}
public void chargePhoneInAmerica() {
socket.chargePhoneInEurope();
}
}
And to use it one would simply adapt the european socket to an american one, sort of like plugging in an adapter in between the two.
public void foo() {
EuropeanSocket europe = new EuropeanSocket();
IChargeAmerican murica = europe.adaptAs(IChargeAmerican.class);
murica.chargePhoneInAmerica();
}
This example shows how the adaptAs method creates a link between the two interfaces IChargeAmerican and IChargeEurope. Even though they don't have anything in common the adapter can act as they do.
Now, the EuropeanSocket implements the IAdaptable interface in order to "convert" itself to another known socket. Usually though the class should not be responsible for this. As the example at wikipedia shows, a factory or provider is better suited for this.
I think that you ask why the method signature
<T> T modelTo(Class<T> clazz);
is used.
The parameter clazz is used to have the type information inside the method implemented. You can then access the type information very easy.
You can then create an object and return it from the implemented method that has the given class.
The method signature looks a bit clumsy but is helpful as the generic information is missing after compilation (type erasure) and the parameters give you the possibility to access the type information (and thereforethe expected return type).
I can imagine it may have been made that way to allow type casting by passing a Class object as a parameter of other methods calling the modelTo(Class clazz) method, or in other words : having other methods casting IModel objects to any class without even knowing which class they will cast it into (nothing even prevents from passing a Class instance to this method which isn't even a subtype of IModel...)
It would be interesting to know how this modelTo method is implemented. Is there a single, final implementation in an abstract skeleton class ? How does it respond to errors (like passing null as the clazz parameter, or triggering a ClassCastException) ? In other words : could this be an attempt to encapsulate all class casts into a single method, to replace ClassCastExceptions with a custom Exception or something like that ? (ClassCastException being a RuntimeException, it could have been a way to make sure a checked exception is thrown instead to enforce explicit exception handling everywhere in the code, I've already seen projects using such an approach...)
I'm trying to simulate something analogous to a function template in Java, in the sense that I have something like the following:
public interface MyFunctionTemplate<T> {
void doSomething(T thing);
}
public class MyIntegerFunctionTemplate extends MyFunctionTemplate<Integer> { ... }
public class MyStringFunctionTemplate extends MyFunctionTemplate<String> { ... }
It appears that I will need a central registry of some sort. Something like the following:
public class MyFunctionTemplateRegistry {
private static Map<Class<?>, MyFunctionTemplate<?>> registry;
public static <T> void register(Class<T> templateClass, MyFunctionTemplate<T> templateFunction);
public static void doSomething(Object thing);
}
What is the best way to design such a thing?
Well, it depends on what you want to achieve and whether the implementing class needs to know the type or not. To me, your suggestion seems overdesigned (too complex), but it is really hard to say without having more concrete information.
The reason I'm saying this, is that I don't like the fact that you want to implement two separate classes for your interface (one for each type). The strength of using generics is often in finding a way to implement it with one class using the generic type T.
Then again, I might have misunderstood your intentions here...
Anyway, as a simple example, if your function(s) are purely mathematical, something like getMax() and getMin(), then you surely don't need to know anything more about T than the fact that T is comparable with T.
Then you could end up with something like this:
public class FindExtremes<T extends Comparable<T>> {
T getMax(T a, T b) {
return a.compareTo(b) >= 0 ? a : b;
}
T getMin(T a, T b) {
return a.compareTo(b) <= 0 ? a : b;
}
}
This could the be used directly for any class that implements Comparable, e.g.
new FindExtremes<Integer>().getMax(4, 5);
new FindExtremes<Double>().getMax(4.444D, 5.555D);
new FindExtremes<String>().getMax("abc", "zyx");
I am starting to work with Java after some projects in C# and C++.
I wanted to design visitor interfaces like this:
public interface ActionVisitor<A> {
void visitAction(A action);
}
public interface MySmallActionVisitor
extends ActionVisitor<ActionA>,
ActionVisitor<ActionB>
{
}
public interface MyFullActionVisitor
extends ActionVisitor<ActionA>,
ActionVisitor<ActionB>,ActionVisitor<ActionC>,ActionVisitor<ActionD> //....
{
}
Of course this doesn't work because of type erasure. (The reason why I want something like this is that I will have different Visitor interfaces for different groups of Actions that can be visited.)
The only solution that comes to my mind is to declare interfaces
public interface ActionAVisitor {
void visitAction(ActionA action);
}
public interface ActionBVisitor {
void visitAction(ActionB action);
}
//...
and then
public interface MySmallActionVisitor
extends ActionAVisitor, ActionBVisitor
{
}
This would work, but I wouldn't like the declaration of all the ActionXVisitor-Interfaces which is stupid repetition and lots of files...
Do you have any ideas how to do this better?
Thanks a lot!
I work with a large and complex library in Java which extensively uses the Visitor Pattern in a very clean and neat way. In particular, I came across with the same problem of type erasure and it is solved now.
If you have a chance, please have a look at an article I've written about this.
It's a long article, which explains in detail what the Visitor pattern is about conceptually and, in last part of the article, it is discussed a real life example which involves polymorphism and type erasure.
Cheers
I would use a single unparameterized visitor interface, then inside the visitor method do the dispatch based on type.
There's no way to be able to avoid instanceof of inside the method. But you can make it more graceful:
public interface MarkerInterface{}
public interface ActionVisitor<T extends MarkerInterface> {
void visitAction(T action);}
public class A implements MarkerInterface{}
public class B implements MarkerInterface{}
public class MySmallActionVisitor implements ActionVisitor<MarkerInterface>{
#Override
public void visitAction(MarkerInterface action) {
if(action instanceof A){
}
else if(action instanceof B){
}
}
}