So I have some classes like BooleanLogger, IntLogger etc., which implement my own Logger interface.
This is the Logger interface:
public interface Logger {
String serialise();
Object deserialise(String value);
void setValue(Object value);
}
Here's a snippet of BooleanLogger:
public class BooleanLogger extends MutableBoolean implements Logger {
private MutableBoolean value;
// ...
#Override
public String serialise() {
return serialise(this.value.booleanValue());
}
public static String serialise(Boolean value) {
return Boolean.toString(value);
}
#Override
public Object deserialise(String value) {
return Boolean.parseBoolean(value);
}
#Override
public void setValue(Boolean value) {
this.value = new MutableBoolean(value);
logChange();
}
#Override
public void setValue(Object value) {
this.value = new MutableBoolean((Boolean) value);
logChange();
}
private void logChange() {
System.out.println(this.value); // temporary
}
}
So the basic idea is essentially to override any setter methods within MutableBoolean such that we log the new value whenever it's modified. I've implemented that part trivially so far, but that's not what I'm concerned about.
Elsewhere in my code, I have a map Map<String, Logger> loggerMap. I want to be able to get a Logger from this map and set its value, given a serialised String value. For example:
Logger logger = loggerMap.get("myLogger1");
logger.setValue(logger.deserialise(value));
It's done this way because I don't know the type of Logger I'm getting, so everything needs to work regardless.
Note the reason for this serialising/deserialising is these values are coming from Redis and hence are stored as Strings.
The problem I'm having is that in the individual loggers like BooleanLogger, it says:
'setValue(T)' in 'org.apache.commons.lang3.mutable.Mutable' clashes
with 'setValue(Object)' in 'myLogger.BooleanLogger'; both methods have
same erasure, yet neither overrides the other
The only solution I can think of is to no longer extend from MutableBoolean, MutableInt etc., and instead just copy all the methods into my own BooleanLogger, IntLogger classes. However, I have these classes for a fair few types and it would quickly become cumbersome and frustrating to do it this way. Right now I only have to deal with any methods that change the underlying value.
As far as the logic goes, I've already successfully implemented everything with my public class ArrayLogger<T> extends ArrayList<T> implements Logger {} as this is the only one that does not extend from a Mutable type that clashes on the setValue method.
EDIT: I've realised that even if I make my own class, I'll have the same issue just
'setValue(Object)' in 'myLogger.BooleanLogger' clashes with
'setValue(T)' in 'org.apache.commons.lang3.mutable.Mutable'; both
methods have same erasure, yet neither overrides the other
Assuming public class BooleanLogger implements Mutable<Boolean>, Serializable, Comparable<MutableBoolean>, Logger {}
So unless I make my own Mutable<T> type (and possibly others...), I may need a different solution.
The root problem is that your code doesn't actually make sense.
This part, specifically:
interface Logger {
void setValue(Object value);
}
You've broken the type system here. That says to me I can call setValue(whateverObjectIPlease) on any logger of any stripe and it should just work. Turns out that is incorrect - if I invoke .setValue(x) on any Logger whose actual type is BooleanLogger, and x is anything but a Boolean instance, it fails.
Hence, this is not great API. Now also consider that it fundamentally clashes with apache's Mutable hierarchy and it gets worse.
There's a second fundamental problem in your design.
Your BooleanLogger class is confused about itself and is its own factory.
Specifically, the deserialize method has nothing to do with a BooleanLogger instance. It doesn't interact with any field whatsoever, and could have been static, other than the fact that you want it to participate in class hierarchies and static methods don't.
That is what factories are for. They let you abstract non-instance parts of class structures (so, constructors, and static methods).
One way to go is to make a LoggerFactory or LoggerType interface, have exactly 1 instance for each type. You'd have something like:
interface LoggerFactory<T extends Logger> {
T deserialize(String in);
}
class BooleanLoggerFactory<BooleanLogger> {
BooleanLogger deserialize(String in) {
return new BooleanLogger(Boolean.parseBoolean(value));
}
}
Voila - you can abstract that way to your hearts content.
But, if you find that too complicated, just 'collapse' your setValue and deserialize methods.
Right now your deserialize method is lying in the sense that it says it is an instance method but it really isn't.. and your setValue method is lying in the sense that it indicates any object of any stripe will do when that isn't the case either.
But... combine the two... and both lies disappear in a puff of smoke. Behold:
interface Logger {
/** Sets the value of this logger by deserializing {#code in}. */
abstract void deserialize(String in);
// completely delete setValue. It has no business being here.
}
class BooleanLogger implements Logger {
#Override public void deserialize(String in) {
setValue(Boolean.parseBoolean(in));
}
public void setValue(boolean b) {
this.v = v;
}
}
Problem solved. If you really insist on having that setValue method be part of Logger itself, introduce generics. It was your choice to sign up to apache's Mutable type hierarchy, and it uses generics, so - you signed up for that too:
public interface Logger<T> {
String serialise();
Object deserialise(String value);
void setValue(T value);
}
public class BooleanLogger implements Logger<Boolean> {
...
#Override public void setValue(Boolean b) {
this.v = b.booleanValue();
}
}
Related
EDIT 1: According to this, despite SomeObject<?> being indeed a superclass of SomeObject<Foo>, Class<SomeObject<?>> is NOT a superclass of Class<SomeObject<Foo>>. The question on how to tackle this specific problem still persists. (adding a method to the Message<T> class that returns Class<Message<T>>, perhaps?)
Original question:
So basically I have a generic Message<T> class that implements a well known design pattern called Command pattern (with a twist: instead of building an object with a reference, the reference is passed as argument of the execute(T objectToCallMethodsOn)) and it looks something like this:
public abstract class Message<T> {
void execute(T obj); //e.g. DoSomethingOnFooMessage implements Message<Foo> to do something on a Foo object
}
so that I can do something like:
public DoSomethingOnFooMessage implements Message<Foo> {
#Override
void execute(Foo obj) {
obj.doSomething(); //doSomething is a method of the Foo class
}
}
Now, I also tried to make a MessageProcessor class with an internal map that maps (E is a type parameter) Class<Message<E>> to a object E executableObject (like Foo in the previous example) and with two methods: a handleMessage(Message<?> msg) that should do a dynamic instanceof of the Message (hence the need for the Class<> objects that let you do a dynamic instanceof and then a dynamic cast) and look for the right executableObject in the map to call the message's execute(E obj) on the right object (if it exists, otherwise the message is discarded), and a addProcessor() to add entries of e.g. Class<Message<Foo>>, Foo to the map:
public class MessageProcessor {
private final Map<Class<Message<?>>, Object> map;
public MessageProcessor() {
map = new HashMap<>();
}
public <E> void addProcessor(Class<Message<E>> messageClass, E executable) {
map.put(messageClass, executable);
}
...
}
So far that's what I wrote but the IDE complains that Class<Message<E>> was given but Class<Message<?>> was needed in addProcessor() and I don't know why; afaik, SomeClass<?> should be a superclass of any SomeClass<SpecificClass>, why isn't it the same for Class<SomeObject<?>> and Class<SomeObject<SpecificObject>>?
Sorry for the verbose question, other than asking a thing about superclassing of generics, I am also asking you guys for (perhaps) a different, more elegant way to do what I'm trying to do, which is find the runtime class of the message so that I can call its execute() with the object that I registered with the addProcessor() as its input.
Also, I reckon this could be easily solvable with raw types (ew)
Context
I am working with very similar classes like RechargeResponse or ConsultResponse. All of them (around 80) are generated from WSDL scheme has the same structure. (This scheme comes from 3PP company, so I can't change this logic.)
Each of them contains inner classes: RechargeResult and ConsultResult.
I have a bunch of methods with same functionality. The only difference is that I need to call (for example) response.get_ClassName_Result().getAny() to check data.
Question
How can I escape from using in every method same code with only ClassNameMethod changed?
Is any solution like Generics, Reflections or some else could be used? (I think parsing classname like string is not a solution).
Code examples below:
Similar classes:
public class ConsultResponse {
protected ConsultResult consultResult;
public ConsultResult getConsultResult() {
return consultResult;
}
public static class ConsultResult {
protected Object any;
public Object getAny() {
return any;
}
public void setAny(Object value) {
this.any = value;
}
}
}
public class RechargeResponse {
protected RechargeResult rechargeResult;
public RechargeResult getRechargeResult() {
return rechargeResult;
}
public static class RechargeResult {
protected Object any;
public Object getAny() {
return any;
}
public void setAny(Object value) {
this.any = value;
}
}
}
Similar (duplicated) method for each class:
private void validateConsult(ConsultResponse response) {
if (response == null ||
response.getConsultResult() == null || // need solution here
response.getConsultResult().getAny() == null) { // need solution or change here
throw new Exception();
}
}
One of the problems is that your get«classname»Result method names include the class names. That makes it impossible to make it generic without using reflection. Why don't you just rename both to getResult? You could then use generics to make the class generic.
First, we define an interface which defines both getAny and setAny.
public interface Result {
Object getAny();
void setAny(Object value);
}
Then we could create an implementation of Result, which is, for example, ConsultResult. You could do the same with RechargeResult.
public class ConsultResult implements Result {
protected Object any; // You already have a getter, so this can also be private
public Object getAny() {
return this.any;
}
public void setAny(Object value) {
this.any = value;
}
}
Then we could create a base class Response, which defines the getResult method. The class accepts a type argument T which must implement Result.
public abstract class Response<T extends Result> {
protected T result; // You already have a getter, so this can also be private
public T getResult() {
return this.result;
}
}
At last, we also create our ConsultResponse class. We extend it from Response, and we provide as type argument ConsultResult.
public class ConsultResponse extends Response<ConsultResult> {
// The field 'result' is already present within the Response class,
// so there is no need to include it here.
}
Also, as GhostCat already said in the comments: what is the point of having two different inner classes in the first place? They're both the same in your example as it is currently written. You could replace them with a single base class; however, it could be that there's more members within those classes which are not shown in your example, so I left them as they were in my example.
For the validation you could do roughly the same.
There are several ways around it, for example by creating a superclass from which ConsultResponse and RechargeResponse would be extending. The superclass would have the shared method defined, so you don't have to define it in the extended classes, unless you'd want to override it.
Another approach would be to separate the validation completely into a separate class, for example a ResponseValidator which would handle the validation on its own and would be included and used in the ConsultResponse and RechargeResponse classes.
It's hard to pinpoint an exact solution to this because it depends on your specific situation which we are not aware of completely.
I'm currently working on a protocol handler for a project of mine in Java. I am trying to create a maintainable and extensible API, meaning I do not want to simply hardcode in supported value types.
I have begun designing a 'protocol handler' that given a value (of a supported type) can encode that value according to the specification of the protocol, without the client worrying about the details of the translation process.
Different value types e.g. Strings or Integers necessarily have different encoding processes, but I don't want clients to worry about holding references to a different object for each possible type they may need to encode - as I said I don't want them to worry about the details.
So far I have defined a 'generic' DynamicHandler class that maintains a collection of 'specific' type aware StaticHandlers:
class DynamicHandler
{
Map<Class, StaticHandler> handlers;
<T> void handle(T value)
{
if(handlers.containsKey(value.class))
handlers.get(value.getType()).handle(value);
}
void <T> register(StaticHandler<T> handler)
{
handlers.put(T.class, handler);
}
}
The idea of this class is that a client simply passes a value they want to encode to the handle method and the DynamicHandler looks up and delegates to the StaticHandler.
interface StaticHandler<T>
{
void handle(T value);
}
Here an example of some client that uses this system:
class StringHandler implements StaticHandler<String>
{
void handle(String value)
{
...
}
}
DynamicHandler handler = new DynamicHandler();
handler.register(new StringHandler());
handler.handle("Hello World!");
I have two questions which I am struggling to find an answer to on my own:
In the DynamicHandler.register method, how can I get the type of T without having an instance of T?
Is it possible to implement the DynamicHandler type as a java.util.Map, in order to maximise compatibility with any 3rd party code clients, may use to build or otherwise process such objects?
Edit: Since DynamicHandler is essentially a Map, albeit with some generic trickery going on, is it possible to implement it as: DynamicHandler implements java.util.Map<...,...> (I'm not exactly sure what the Key and Value types should be here).
This is my first time asking a question on here, so I hope that I have been clear enough for you all. If there is anything you think needs clarifying just let me know and I will try my best.
If null values are not handled and that it is designed such that there would never be any value that belongs to multiple classes, then you could do this:
public class DynamicHandler {
Map<Class, StaticHandler> handlers;
public <T> void handle(T value) {
if(value != null) {
handlers.entrySet()
.stream()
.filter(entry ->
entry.getKey().isInstance(value))
.findAny()
.ifPresent(entry ->
entry.getValue().handle(value));
}
}
public void <T> register(StaticHandler<T> handler) {
handlers.put(handler.getHandlingClass(), handler);
}
}
interface StaticHandler<T>
{
void handle(T value);
Class<T> getHandlingClass();
}
public class StringHandler implements StaticHandler<String> {
#Override public void handle(String value) {
...
}
#Override public final Class<String> getHandlingClass() {
return String.class;
}
}
In the DynamicHandler class, how can I get the type of T without having an instance of T?
The common solution for this is to pass it a Class object:
void <T> register(StaticHandler<T> handler, Class<T> clazz)
{
handlers.put(clazz, handler);
}
Just as one example of this in a commonly used library: Gson does something similar to register JSON serializers for specific types with GsonBuilder.registerTypeHierarchyAdapter
If I have two interfaces , both quite different in their purposes , but with same method signature , how do I make a class implement both without being forced to write a single method that serves for the both the interfaces and writing some convoluted logic in the method implementation that checks for which type of object the call is being made and invoke proper code ?
In C# , this is overcome by what is called as explicit interface implementation. Is there any equivalent way in Java ?
No, there is no way to implement the same method in two different ways in one class in Java.
That can lead to many confusing situations, which is why Java has disallowed it.
interface ISomething {
void doSomething();
}
interface ISomething2 {
void doSomething();
}
class Impl implements ISomething, ISomething2 {
void doSomething() {} // There can only be one implementation of this method.
}
What you can do is compose a class out of two classes that each implement a different interface. Then that one class will have the behavior of both interfaces.
class CompositeClass {
ISomething class1;
ISomething2 class2;
void doSomething1(){class1.doSomething();}
void doSomething2(){class2.doSomething();}
}
There's no real way to solve this in Java. You could use inner classes as a workaround:
interface Alfa { void m(); }
interface Beta { void m(); }
class AlfaBeta implements Alfa {
private int value;
public void m() { ++value; } // Alfa.m()
public Beta asBeta() {
return new Beta(){
public void m() { --value; } // Beta.m()
};
}
}
Although it doesn't allow for casts from AlfaBeta to Beta, downcasts are generally evil, and if it can be expected that an Alfa instance often has a Beta aspect, too, and for some reason (usually optimization is the only valid reason) you want to be able to convert it to Beta, you could make a sub-interface of Alfa with Beta asBeta() in it.
If you are encountering this problem, it is most likely because you are using inheritance where you should be using delegation. If you need to provide two different, albeit similar, interfaces for the same underlying model of data, then you should use a view to cheaply provide access to the data using some other interface.
To give a concrete example for the latter case, suppose you want to implement both Collection and MyCollection (which does not inherit from Collection and has an incompatible interface). You could provide a Collection getCollectionView() and MyCollection getMyCollectionView() functions which provide a light-weight implementation of Collection and MyCollection, using the same underlying data.
For the former case... suppose you really want an array of integers and an array of strings. Instead of inheriting from both List<Integer> and List<String>, you should have one member of type List<Integer> and another member of type List<String>, and refer to those members, rather than try to inherit from both. Even if you only needed a list of integers, it is better to use composition/delegation over inheritance in this case.
The "classical" Java problem also affects my Android development...
The reason seems to be simple:
More frameworks/libraries you have to use, more easily things can be out of control...
In my case, I have a BootStrapperApp class inherited from android.app.Application,
whereas the same class should also implement a Platform interface of a MVVM framework in order to get integrated.
Method collision occurred on a getString() method, which is announced by both interfaces and should have differenet implementation in different contexts.
The workaround (ugly..IMO) is using an inner class to implement all Platform methods, just because of one minor method signature conflict...in some case, such borrowed method is even not used at all (but affected major design semantics).
I tend to agree C#-style explicit context/namespace indication is helpful.
The only solution that came in my mind is using referece objects to the one you want to implent muliple interfaceces.
eg: supposing you have 2 interfaces to implement
public interface Framework1Interface {
void method(Object o);
}
and
public interface Framework2Interface {
void method(Object o);
}
you can enclose them in to two Facador objects:
public class Facador1 implements Framework1Interface {
private final ObjectToUse reference;
public static Framework1Interface Create(ObjectToUse ref) {
return new Facador1(ref);
}
private Facador1(ObjectToUse refObject) {
this.reference = refObject;
}
#Override
public boolean equals(Object obj) {
if (obj instanceof Framework1Interface) {
return this == obj;
} else if (obj instanceof ObjectToUse) {
return reference == obj;
}
return super.equals(obj);
}
#Override
public void method(Object o) {
reference.methodForFrameWork1(o);
}
}
and
public class Facador2 implements Framework2Interface {
private final ObjectToUse reference;
public static Framework2Interface Create(ObjectToUse ref) {
return new Facador2(ref);
}
private Facador2(ObjectToUse refObject) {
this.reference = refObject;
}
#Override
public boolean equals(Object obj) {
if (obj instanceof Framework2Interface) {
return this == obj;
} else if (obj instanceof ObjectToUse) {
return reference == obj;
}
return super.equals(obj);
}
#Override
public void method(Object o) {
reference.methodForFrameWork2(o);
}
}
In the end the class you wanted should something like
public class ObjectToUse {
private Framework1Interface facFramework1Interface;
private Framework2Interface facFramework2Interface;
public ObjectToUse() {
}
public Framework1Interface getAsFramework1Interface() {
if (facFramework1Interface == null) {
facFramework1Interface = Facador1.Create(this);
}
return facFramework1Interface;
}
public Framework2Interface getAsFramework2Interface() {
if (facFramework2Interface == null) {
facFramework2Interface = Facador2.Create(this);
}
return facFramework2Interface;
}
public void methodForFrameWork1(Object o) {
}
public void methodForFrameWork2(Object o) {
}
}
you can now use the getAs* methods to "expose" your class
You can use an Adapter pattern in order to make these work. Create two adapter for each interface and use that. It should solve the problem.
All well and good when you have total control over all of the code in question and can implement this upfront.
Now imagine you have an existing public class used in many places with a method
public class MyClass{
private String name;
MyClass(String name){
this.name = name;
}
public String getName(){
return name;
}
}
Now you need to pass it into the off the shelf WizzBangProcessor which requires classes to implement the WBPInterface... which also has a getName() method, but instead of your concrete implementation, this interface expects the method to return the name of a type of Wizz Bang Processing.
In C# it would be a trvial
public class MyClass : WBPInterface{
private String name;
String WBPInterface.getName(){
return "MyWizzBangProcessor";
}
MyClass(String name){
this.name = name;
}
public String getName(){
return name;
}
}
In Java Tough you are going to have to identify every point in the existing deployed code base where you need to convert from one interface to the other. Sure the WizzBangProcessor company should have used getWizzBangProcessName(), but they are developers too. In their context getName was fine. Actually, outside of Java, most other OO based languages support this. Java is rare in forcing all interfaces to be implemented with the same method NAME.
Most other languages have a compiler that is more than happy to take an instruction to say "this method in this class which matches the signature of this method in this implemented interface is it's implementation". After all the whole point of defining interfaces is to allow the definition to be abstracted from the implementation. (Don't even get me started on having default methods in Interfaces in Java, let alone default overriding.... because sure, every component designed for a road car should be able to get slammed into a flying car and just work - hey they are both cars... I'm sure the the default functionality of say your sat nav will not be affected with default pitch and roll inputs, because cars only yaw!
I would like to extend a class and then copy the value from an instance of the class which has been extended, so I get all its parameters in my new class. In case this doesn't make sense, a simple example of what I'm trying to do:
public class MyTableModel extends DefaultTableModel {
public MyTableModel(DefaultTableModel model){
this = (MyTableModel) model; /* I realise this is invalid */
}
public newMethod(){
// Some additional code
}
}
Is this possible to achieve?
It looks like you want composition instead of inheritance. In particular, it looks like you're trying to use the decorator pattern. That is, you want to take an existing instance of DefaultTableModel, and create another DefaultTableModel that forwards most of the methods to the underlying delegate, but perhaps adding/modifying/decorating some functionalities.
You can never set this = somethingElse;, but you can have a DefaultTableModel delegate, and forward most/all requests to delegate, perhaps adding/decorating some methods as necessary.
See also
Effective Java 2nd Edition, Item 16: Favor composition over inheritance
Guava Example: ForwardingCollection
An example of this pattern is ForwardingCollection from Guava:
A java.util.Collection which forwards all its method calls to another collection. Subclasses should override one or more methods to modify the behavior of the backing collection as desired per the decorator pattern.
You can see the source code to see how this pattern is typically implemented:
#Override protected abstract Collection<E> delegate();
public int size() {
return delegate().size();
}
public boolean isEmpty() {
return delegate().isEmpty();
}
public boolean removeAll(Collection<?> collection) {
return delegate().removeAll(collection);
}
// many more interface Collection methods implemented like above...
As you can see, all the ForwardingCollection does is it implements Collection simply by forwarding all methods to its delegate(), another Collection. Understandably this is rather repetitive and mundane code to write, but now subclasses can simply extends ForwardingCollection and only decorate what they want to decorate.
You can't not set this in Java to anything, it is just used for expressions like (this == someObject) or accessing some property of the object being currently used like (this.someProperty) or inside a constructor to initialize the current object. See here for more info about the this keyword
This code will likely throw a java.lang.ClassCastException
That is MyTableModel is a DefaultTableModel but DefaultTableModel is not a MyTableModel. See http://java.sun.com/docs/books/jls/third_edition/html/conversions.html for more details about type conversion in java
If there is some state and/or behavior that you want to reuse from your parent class in your subclass you should consider marking those members as protected, or consider other form of composition.
A better way to do this would be to make the fields of the superclass protected instead of private - this will give you access to them in your subclass.
Note that when you defined the subclass constructor, you will need to call a constructor from the superclass as well, so in that respect you'll still be able to pass in all the required variables.
And don't forget that all public methods in the superclass can be called as-is by any code that has an instance of your subclass.
EDIT: A little example might help:
public class DefaultTableModel
{
protected String modelName;
protected int numberOfTables;
private numTimesReinited = 0;
public DefaultTableModel(String name, int numTabs)
{
modelName = name;
numberOfTables = numTabs;
}
public void reinit()
{
numTimesReinited++;
// Other stuff
}
protected int getNumberOfReinits()
{
return numTimesReinited;
}
public String getName()
{
return name;
}
}
public class MyTableModel extends DefaultTableModel
{
private String modelType;
public MyTableModel(String name, int numTables, String modelType)
{
super(name, numTables); // sets up the fields in the superclass
this.modelType = modelType;
}
// purely "local" code
public void getModelType()
{
return modelType;
}
// Accesses several protected data to provide new (public) functionality
public void addTable()
{
if (getNumberOfReinits() < 10)
{
numberOfTables++;
reinit();
}
}
}
Let me know if I've misunderstood your requirements, but it sounds like you want to access fields and behaviour of the superclass - which you'll have automatic access to in your subclass so long as they're not private.