I would like to write a generic algorithm, which can be instantiated with different objects. The objects are coming from 3rdparty and they have no common base class. In C++, I just write the generic algorithm as a template which takes the particular object as its argument. How to do it in Java?
template <class T>
class Algorithm
{
void Run(T& worker)
{
...
auto value = workder.DoSomething(someArgs);
...
}
};
In C++, I don't need to know anything about the T, because the proper types and availability of methods are checked during compilation. As far as I know,
in Java I must have a common base class for all my workers to be able to call methods on them. Is it right? Is there a way how to do similar stuff in Java?
I can't change my 3rdparty workers, and I don't want to make my own abstraction of all workers (including all types which the workers are using, etc.).
Edit:
Since I want to write the generic algorithm only once, maybe it could be a job for some templating language which is able to generate Java code (the arguments to the code template would be the workers)?
My solution:
In my situation, where I cannot change the 3rdparty workers, I have chosen Java code generation. I have exactly the same algorithm, I only need to support different workers which all provides identical interface (classes with same names, same names of methods, etc.). And in few cases, I have to do a small extra code for particular workers.
To make it more clear, my "workers" are in fact access layers to a proprietary DB, each worker for a single DB version (and they are generated).
My current plan is to use something like FreeMaker to generate multiple Java source files, one for each DB version, which will have only different imports.
The topic to look into for you: generics
You can declare a class like
public class Whatever<T> {
which uses a T that allows for any reference type. You don't need to further "specialize" that T mandatorily. But of course: in this case you can only call methods from Object on instances of T.
If you want to call a more specific method, then there is no other way but somehow describing that specification. So in your case, the reasonable approach would be to introduce at least some core interfaces.
In other words: there is no "duck typing" in Java. You can't describe an object by only saying it has this or that method. You always need a type - and that must be either a class or an interface.
Duck typing isn't supported in Java. It can be approximated but you won't get the convenience or power you're used to in C++.
As options, consider:
Full-on reflection + working with Object - syntax will be terrible and the compiler won't help you with compilation checks.
Support a pre-known set of types and use some sort of static dispatching, e.g a big switch / if-else-if block, a type -> code map, etc. New types will force changing this code.
Code generation done during annotation processing - you may be able to automate the above static-dispatch approach, or be able to create a wrapper type to each supported type that does implement a common interface. The types need to be known during compilation, new types require recompilation.
EDIT - resources for code generation and annotation processing:
Annotation processing tutorial by #sockeqwe
JavaPoet, a clean code generation tool by Square
If you really don't have any way to get it done correctly with generics you may need to use reflection.
class A {
public String doIt() {
return "Done it!";
}
}
class B {
public Date doIt() {
return Calendar.getInstance().getTime();
}
}
interface I {
public Object doIt();
}
class IAdapter implements I {
private final Object it;
public IAdapter(Object it) {
this.it = it;
}
#Override
public Object doIt() {
// What class it it.
Class<?> itsClass = it.getClass();
// Peek at it's methods.
for (Method m : itsClass.getMethods()) {
// Correct method name.
if (m.getName().equals("doIt")) {
// Expose the method.
m.setAccessible(true);
try {
// Call it.
return m.invoke(it);
} catch (Exception e) {
throw new RuntimeException("`doIt` method invocation failed", e);
}
}
}
// No method of that name found.
throw new RuntimeException("Object does not have a `doIt` method");
}
}
public void test() throws Exception {
System.out.println("Hello world!");
Object a = new IAdapter(new A()).doIt();
Object b = new IAdapter(new B()).doIt();
System.out.println("a = "+a+" b = "+b);
}
You should, however, make every effort to solve this issue using normal type-safe Java such as Generics before using reflection.
In Java all your Workers must have a method DoSomething(someArgs), which doesn't necessarily imply that they extend the same base class, they could instead implement an interface Worker with such a method. For instance:
public interface Worker {
public Double DoSomething(String arg1, String arg2);
}
and then have different classes implement the Worker interface:
One implementation of Worker:
public class WorkerImplA implements Worker{
#Override
public Double DoSomething(String arg1, String arg2) {
return null; // do something and return meaningful outcome
}
}
Another implementatin of Worker:
public class WorkerImplB implements Worker{
#Override
public Double DoSomething(String arg1, String arg2) {
return null; // do something and return meaningful outcome
}
}
The different WorkerImpl classes do not need to extend the same common base class with this approach, and as of JavaSE 8 interfaces can have a default implementation in any method they define.
Using this approach Algorithm class would look like:
public class Algorithm {
private String arg1;
private String arg2;
public Algorithm(String arg1, String arg2){
this.arg1 = arg1;
this.arg2 = arg2;
}
public void Run(Worker worker){
worker.DoSomething(arg1, arg2);
}
}
Related
I have a Java class Model which models some data from my remote database. I want all data models in my project to be able to supply a builder from a Map<String, Object> instance (in practice, I'm working with SnapshotParser<Model> parsers with Firestore, but I'll just call getData() in every model). This should look something like:
public class Model {
private String name;
public Model(String name) { this.name = name; }
public static SnapshotParser<Model> getDocParser() {
return docSnapshot -> {
Map<String, Object> data = docSnapshot.getData();
return new Model(data.getOrDefault("name", "John Doe"));
};
}
}
Note that I'll have several models (Model2, Model3...) which will also be required to provide such an interface. To enforce this behavior, I created a DocParserSupplier generic class for my model classes to implement:
public interface DocParserSupplier<T> {
static SnapshotParser<T> getDocParser();
}
This doesn't work for two reasons (as Android Studio informs me):
static methods of interfaces must have a default implementation. I can't do that without knowing T.
I get the "T cannot be referenced in static context" error.
If remove the static keyword from the above interface, I can do what I want but it would require I create an actual instance of the Model to get the parser. It would work but it makes more sense if the method is static.
Is there a Java way to do what I want?
EDIT: My specific use case is in matching RecyclerViews to documents in my database. Constructing the FirestoreRecyclerOptions object requires a parser to convert key-value data to a Model:
FirestoreRecyclerOptions<Model1> fro1 = new FirestoreRecyclerOptions.Builder<Model1>()
.setQuery(query1, Model1.getDocParser())
.build();
FirestoreRecyclerOptions<Model2> fro2 = new FirestoreRecyclerOptions.Builder<Model2>()
.setQuery(query2, Model2.getDocParser())
.build();
Interfaces enforce behavior of instances, so that references to any object which has that behavior can be passed around in a type-safe way. Static methods on the other hand, don't belong to any particular instance of an object; the class name is essentially just a namespace. If you want to enforce behavior, you will have to create an instance somewhere (or use reflection, if it is absolutely necessary to ensure a class has a particular static method).
Unless this system is going to be opened up for extension, where others can define their own models, I would say ditch the DocParserSupplier interface altogether and call the static methods exactly as you are now, or factor them out into a factory interface + implementation. The factory option is nice because you can replace the production implementation with a fake implementation that returns dummy parsers for tests.
Edit: Doc Parser Factory
public interface DocParserFactory {
SnapshotParser<Model1> getModel1Parser();
SnapshotParser<Model2> getModel2Parser();
...
SnapshotParser<Model1> getModelNParser();
}
...
// The implementation of each getModelXParser method
class DocParserFactoryImpl {
SnapshotParser<Model1> getModel1Parser() {
return docSnapshot -> {
Map<String, Object> data = docSnapshot.getData();
return new Model(data.getOrDefault("name", "John Doe"))};
}
...
}
...
private DocParserFactory docParserFactory;
// You can inject either the real instance (DocParserFactoryImpl) or a
// test instance which returns dummy parsers with predicable results
// when you construct this object.
public ThisObject(DocParserFactory docParserFactory) {
this.docParserFactory = docParserFactory;
}
...
// Your code
public void someMethod() {
...
FirestoreRecyclerOptions<Model1> fro1 = new
FirestoreRecyclerOptions.Builder<Model1>()
.setQuery(query1, docParserFactory.getModel1Parser())
.build();
FirestoreRecyclerOptions<Model2> fro2 = new
FirestoreRecyclerOptions.Builder<Model2>()
.setQuery(query2, docParserFactory.getModel2Parser())
.build();
...
}
It's not so much to do with static or non-static, as it is with the fact that you cannot create an instance of a generic object without passing the type parameter(s) one way or another. In fact, I answered a similar question a few days ago, when somebody wanted to use enums to get the required builder.
In short, you cannot write a method <T extends AbstractBuilder> T builder(final SomeNonGenericObject object) (or, in this case, <T extends AbstractBuilder> T builder()) without passing T in some form. Even though it will make sense at runtime, the compiler can't figure out what generic type to use if you don't tell it which one it is.
In Java 8, you can solve this elegantly with method references. I don't know much about Android, but I believe you're still on Java 6 there, so this wouldn't work.
Anyway, you can have something like the following:
public <T extends AbstractBuilder> T builder(final Supplier<T> object) {
return supplier.get();
}
final Supplier<AbstractBuilder> model1BuilderSupplier = Model1Builder::new;
builder(model1BuilerSupplier)
.setQuery(query1, Model1.getDocParser())
.build();
It's not exactly what you want, but the way you're trying to go about it will not work.
I am trying to port an SDK written in java to C#.
In this software there are many "handler" interfaces with several methods (for example: attemptSomethingHandler with success() and several different failure methods). This interface is then implemented and instantiated anonymously within the calling class and passed to the attemptSomething method of the SomethingModel class. This is an async method and has several places where it could fail or calls another method (passing on the handler). This way, the anonymous implementation of attemptSomethingHandler can reference private methods in the class that calls attemptSomething.
In C# it is not possible to anonymously implement an interface. I could explicitly implement a new class, but this implementation would be unique to this calling class and not used for anything else. More importantly, I would not be able to access the private methods in the calling class, which I need and do not want to make public.
Basically, I need to run different code from the calling class depending on what happens in the SomethingModel class methods.
I've been reading up on delegates but this would require passing as many delegates as there are methods in the handler interface (as far as I can tell).
What is the appropriate way to do this in C#? I feel like I'm missing out on a very common programming strategy. There simply must be an easy, clean way to structure and solve this problem.
Using delegates:
void AttemptSomethingAsync(Action onSuccess, Action<string> onError1, Action onError2 = null) {
// ...
}
// Call it using:
AttemptSomethingAsync(onSuccess: () => { Yes(); }, onError1: (msg) => { OhNo(msg); });
Or, using a class
class AttemptSomethingHandler {
Action OnSuccess;
Action<string> OnError1;
Action OnError2;
}
void AttemptSomethingAsync(AttemptSomethingHandler handler) {
// ...
}
// And you call it like
AttemptSomethingAsync(new AttemptSomethingHandler() {
OnSuccess = () => { Yes() };
});
Or events
public delegate void SuccessHandler();
public delegate void ErrorHandler(string msg);
class SomethingModel {
public event SuccessHandler OnSuccess;
public event ErrorHandler OnError1;
public void AttemptSomethingAsync() {
// ...
}
}
// Use it like
var model = new SomethingModel();
model.OnSuccess += Yes;
model.AttemptSomethingAsync();
private void Yes() {
}
In C#, we don't have anonymous types like Java per se. You can create an anonymous type which contains fields like so:
var myObject = new { Foo = "foo", Bar = 1, Quz = 4.2f }
However these cannot have methods placed in them and are only passable into methods by use of object or dynamic (as they have no type at compile-time, they are generated by the compiler AFAIK)
Instead in C# we use, as you said, delegates or lambdas.
If I understand your pickle correctly, you could implement a nested private class like so:
interface IMyInterface
{
void Foo();
}
class MyClass
{
public void Bar()
{
var obj = new MyInterface();
obj.Foo();
}
private class MyInterface : IMyInterface
{
public void Foo()
{
// stuff
}
}
}
Now MyClass can create an instance of MyInterface which implements IMyInterface. As commentors have mentioned, MyInterface can access members of MyClass (although you most certainly want to try and stick to using publicly accessible members of both types).
This encapsulates the "anonymous" class (using Java terms here to make it simpler) and also means that you could potentially return MyInterface as an IMyInterface and the rest of the software would be none the wiser. This is actually how some abstract factory patterns work.
Basically, I need to run different code from the calling class depending on what happens in the SomethingModel class methods.
This smells of heavy coupling. Oh dear!
It sounds to me like your particular problem could use refactoring. In C# you can use Events to solve this (note: Can, not should). Just have an Event for each "branch" point of your method. However I must say that this does make your solution harder to envisage and maintain.
However I suggest you architect your solution in a way such that you don't need such heavy coupling like that.
You could also try using a Pipeline model but I'm not sure how to implement that myself. I know that jetty (or is it Netty? the NIO for Java by JBOSS) certainly used a similar model.
You may find that throwing out some unit tests in order to test the expected functionality of your class will make it easier to architect your solution (TDD).
You can use nested classes to simulate anonymous classes, but in order to use nested classes in the same way as Java you will need to pass a reference to the outer class. In Java all nested and anonymous classes have this by default, and only static ones do not.
interface IMyInterface
{
void Foo();
}
class MyClass
{
public void Bar()
{
IMyInterface obj = new AnonymousAnalog(this);
obj.Foo();
}
private class AnonymousAnalog : IMyInterface
{
public void Foo(MyClass outerThis)
{
outerThis.privateFieldOnOuter;
outerThis.PrivateMethodOnOuter();
}
}
...
}
Can the JVM perform runtime optimization in the following scenario?
We've got the following situation, we have this interface:
public interface ECSResource {
default int getFor(final Entity entity) {
return ResourceRetriever.forResource(this).getFor(entity);
}
}
And a concrete implementation such as:
private static enum TestResources implements ECSResource {
TR1, TR2;
}
Would the JVM be able to figure out (at runtime) that an enum instance such as TestResources.TR1 belongs to a single ResourceRetriever like ResourceRetriever.forResource(TestResources.TR1)?
In the naive implementation every call to TestResources.TR1.getFor(...) would create a new ResourceRetriever instance.
In this case though, we know that (by code inspection) a call to ResourceRetriever.forResource(this) will call the following:
public class ResourceRetriever {
private final ECSResource resource;
ResourceRetriever(ECSResource resource) {
this.resource = resource;
}
public static ResourceRetriever forResource(ECSResource resource) {
return new ResourceRetriever(resource);
}
//lots of methods
}
Hence there is nothing that can change at runtime due to random results, rounding errors, etc.
Hence the question: Can the JVM map every enum ECSResource instance to its unique corresponding ResourceRetriever.forResource(this) instance?
Note that it is possible to do such thing by your own, via the following:
private static enum TestResources implements ECSResource {
TR1, TR2;
private static final Map<TestResources, ResourceRetriever> retrieverMapping;
static {
retrieverMapping = Arrays.stream(TestResources.values())
.collect(Collectors.toMap(res -> res, ResourceRetriever::forResource));
}
#Override
public int getFor(final Entity entity) {
return retrieverMapping.get(this).getFor(entity);
}
}
The semantics of the new keyword almost certainly prohibit what you're wanting to do. (See references both in The Java Language Specification and The Java Virtual Machine Specification.) Your forResource method is always going to return a new object. I don't know of any JVMs that would do what you're trying to do, given that there is no mechanism to determine that only one ResourceRetriever should be created for any given ECSResource. This looks like a form of memoization to me, which would be handled by the language (e.g. Groovy, which has an annotation specifically for this) and not by the runtime (JVM). If Java had reified generics, you could possibly hack such a feature with something like ResourceRetriever<? extends ECSResource> but I can't say whether that would actually work, much less whether it would be a good idea or not.
My problem is as follows:
We have an Algorithm that works internally with
Expression-objects that have a "String getContent()" method
Manipulator-objects that manipulate on Expressions using the "Expression manipulate(Expression e)" method
This will become a framework in Java.
To solve a real problem, one needs to give a specific implementation
of both an Expression and a Manipulator and the Algorithm class will do the rest.
Let's say we need a ProblemExpression and a ProblemManipulator
for a specific problem.
The ProblemExpression may contain a lot of new fields,
which can be used by the ProblemManipulator.
Right now, I can only think of two ways to write clean code:
Let ProblemManipulator.manipulate assume its arguments are ProblemExpressions
Use instanceOf
But I've got the feeling this is not how I should do it.
Any other suggestions?
Regards and thank you in advance,
Xaero.
Sounds like you should use a Generic. Like
interface Manipulator<E extends Expression> {
public void manipulate(E expression);
}
class ProblemManipulator implements Manipulator<ProblemExpression> {
public void manipulate(ProblemExpression expression) {
// expression is a ProblemExpression
}
}
As "Problem" is a different problem, it can be an interface that extends Expression like so:
interface IProblemExpr extends Expression
{ //additional methods
}
class ProblemExpression implements IProbExpr
{
}
class ProblemManipulator()
{
ProblemManipulator(IProblemExpr expr)
{
..
}
}
Generics are not enough, if both ProblemExpresions and ProblemManipulators can be accessed publicly.
At first i thought some kind of factory framework would do the trick.
I.e., either Expressions need to be able to create Manipulators or vice-versa.
for example, say ProblemManipulators were private inner classes of ProblemExpressions - obtained from Expression#createManipulator(...).
However, this does not quite do the trick ... in the end, if the Algorithm is allowed to 'hold onto references to' both the Expression and Manipulator, and can obtain different unrelated implementations, then the Algorithm implementation can always (if incorrectly written) wind up invoking the wrong Manipulator for a given Expression - nothing can be done at compile time to prevent this runtime mistake as all Manipulators can be invoked with any Expression.
So, it seems to me that invocation of the Manipulator (or Expression) must 'go thru' the Expression (or conversely the Manipulator) thus ensuring that the correct Manipulator is invoked for the given Expression.
I.e., Expression needs 'manipulate()' method which delegates to the appropriate Manipulator.
I studied the way generics work, and I came up with the following solution:
First, I created a two classes, one for the expression and one for the manipulator:
public class ObjectExpression { }
public class ObjectManipulator <E extends ObjectExpression> {
public void calculate(Set<E> objects) {
... // Do something
}
}
Next, I created an Algorithm class, which is generic.
Two classes are needed:
Some expression
Something that manipulates this type of object
We get:
public class Algorithm <F extends ObjectExpression, E extends ObjectManipulator<F>> {
E om;
public Algorithm( E om ) {
this.om = om;
}
public void run(Set<F> objects) {
om.calculate(objects);
}
}
Then, I created an implementation for the String case:
we need an expression and a manipulator
public class StringExpression extends ObjectExpression {
}
public class StringManipulator extends ObjectManipulator<StringExpression> {
#Override
public void calculate(Set<StringExpression> objects) {
// Do String stuff
}
}
Then, we can run the Algorithm as follows for Objects:
Algorithm<ObjectExpression, ObjectManipulator<ObjectExpression>> algo1 = new Algorithm<ObjectExpression, ObjectManipulator<ObjectExpression>>(manipo);
Set<ObjectExpression> objects = new HashSet<ObjectExpression>();
... // fill set
algo1.run(objects);
And for Strings:
StringManipulator manips = new StringManipulator();
Algorithm<StringExpression, StringManipulator> algo2 = new Algorithm<StringExpression, StringManipulator>(manips);
Set<StringExpression> strings = new HashSet<StringExpression>();
... // fill set
algo2.run(strings);
To me, this seems an elegant solution.
What do you think?
Any alternatives/improvements?
There is a part in my java code where I am extending a class from a library which I haven't written.
#override
public Object getPropertyValue(Object id) {
if(id.equals(model.PROPERTY_RENAME))
model.setName((String)value);
else if(id.equals(model.PROPERTY_COLOUR))
model.setColor((Color)value);
}
Now in this case how should I modify this code to make it scalable. There would be many more properties like location, dimension, etc. Now this model is instance of an abstract class AbsModel.
So every class implementing the AbsModel would have different properties. So the class architecture should be there, so that this part of code remains unchanged, no matter how many more model classes I add.
It looks like you want to carry out some operation on the model when this method (getPropertyValue) is called. I would create a Map of id onto the interface ModelOperation defined as follows:
public interface ModelOperation {
void operate(Object value);
}
Then the map would be defines as follows:
map.put(model.PROPERTY_RENAME, new RenameOperation(model));
Your extension class would then look like this:
#Override
public Object getPropertyValue(Object id) {
map.get(id).operate(model);
// etc...
}
For example, RenameOperation would be defined like this:
public class RenameOperation implements ModelOperation {
public RenameOperation(Model model) {
// etc...
}
public void operate(Object value) {
model.setName((String)value);
}
}
This allows you to support as many model operations as you like and means you don't have to change the extension class you have to write. The above is just an outline. You could use generics on the ModelOperation implementations to avoid the cast of the value in each one.
I guess reflection is probably the answer here if you can rely on some naming to help direct you.
It's not going to be nice, but the idea would be that you'd have a method that would reflect on the type and look up the appropriate method. The code belwo
public Object setPropertyValue(Object id) {
String className = id.getClass().getSimpleName();
// Hope that the method is called set<CLASS> and takes a single parameter that is the class
Method method = model.class.getMethod("set" + className, id.getClass());
// Invoke the method (TODO deal with all of the exceptions)
method.invoke(model, id);
}
There are multiple ways of doing this -- though it depends on what do you mean by "scalable" (being able to cope with lots of requests per second or being able to cope with lots of properties?):
one way -- if you're going to go down the path you have outlined in your code is to have those properties that are used very often at the top of your if/then/else block -- so their execution path is very short. this would "scale up" well for lots of requests as not too much time is being spent in actually executing the method (in most cases at least!)
another way -- and this scales up well for lots of properties and easiness of maintaining the code but you will take a hit on execution time: have a Map that maps property names to setxxx() method names, then you can use reflection to invoke these methods on the target object (id in your case) on each call. Classes extended your class will only have to provide a getMap() method which will return the mapping name-to-setter method, which can be a static member and initialized on class load.
Store your properties in a Map -- in which case setName() is the same as map.put( PROPERTY_RENAME, value)
Since in Java functions are not first class citizens, the "nice" route would be very awkward: define an enum with one value per each constant above (i.e. for each property), and a virtual method e.g. update(Object value, then override the method in each enum to update the corresponding property. If you can, redefine the constants PROPERTY_RENAME etc. themselves as enums. This still results in code bloat.
The other way is to use reflection. If you can use the same ids as the property names you want to update, you only need to invoke the setter for the property (as illustrated in other answers). Otherwise you may need to introduce a mapping from ids to property names.
A version not using reflection, call the base class's implementation:
public Object getValue(Object id) {
Object ret = super.getValue(id);
if (ret == null) {
// Subclass specific properties
}
return ret;
}
A common way around this is to use reflection like
public Object getValue(IdType id) {
Method getter = model.getClass().getMethod("get" + id);
return getter.invoke(model); // throws Exceptions.
}
OR
public void setValue(IdType id, Object value) {
Method setter = model.getClass().getMethod("set" + id, value.getClass());
setter.invoke(model, value); // throws Exceptions.
}
I solved this issue by creating an interface. So the code is.
public interface IModel
{
public void setProperty(String propertyName);
}
Rest of the classes were
public class HelloModel implements IModel
{
public void setProperty(String propertyName)
{ code for handling the properties goes here ... }
}
So in this case every class has to handle it's own property setters.
Is this the best way to handle abstraction ? I think this model is very scalable ...