I have a number of dumb object classes that I would like to serialize as Strings for the purpose of out-of-process storage. This is a pretty typical place to use double-dispatch / the visitor pattern.
public interface Serializeable {
<T> T serialize(Serializer<T> serializer);
}
public interface Serializer<T> {
T serialize(Serializeable s);
T serialize(FileSystemIdentifier fsid);
T serialize(ExtFileSystemIdentifier extFsid);
T serialize(NtfsFileSystemIdentifier ntfsFsid);
}
public class JsonSerializer implements Serializer<String> {
public String serialize(Serializeable s) {...}
public String serialize(FileSystemIdentifier fsid) {...}
public String serialize(ExtFileSystemIdentifer extFsid) {...}
public String serialize(NtfsFileSystemIdentifier ntfsFsid) {...}
}
public abstract class FileSystemIdentifier implements Serializeable {}
public class ExtFileSystemIdentifier extends FileSystemIdentifier {...}
public class NtfsFileSystemIdentifier extends FileSystemIdentifier {...}
With this model, the classes that hold data don't need to know about the possible ways to serialize that data. JSON is one option, but another serializer might "serialize" the data classes into SQL insert statements, for example.
If we take a look at the implementation of one of the data classes, the impementation looks pretty much the same as all the others. The class calls the serialize() method on the Serializer passed to it, providing itself as the argument.
public class ExtFileSystemIdentifier extends FileSystemIdentifier {
public <T> T serialize(Serializer<T> serializer) {
return serializer.serialize(this);
}
}
I understand why this common code cannot be pulled into a parent class. Although the code is shared, the compiler knows unambiguously when it is in that method that the type of this is ExtFileSystemIdentifier and can (at compile time) write out the bytecode to call the most type-specific overload of the serialize().
I believe I understand most of what is happening when it comes to the V-table lookup as well. The compiler only knows the serializer parameter as being of the abstract type Serializer. It must, at runtime, look into the V-table of the serializer object to discover the location of the serialize() method for the specific subclass, in this case JsonSerializer.serialize()
The typical usage is to take a data object, known to be Serializable and serialize it by giving it to a serializer object, known to be a Serializer. The specific types of the objects are not known at compile time.
List<Serializeable> list = //....
Serializer<String> serializer = //....
list.stream().map(serializer::serialize)
This instance works similar to the other invocation, but in reverse.
public class JsonSerializer implements Serializer<String> {
public String serialize(Serializeable s) {
s.serialize(this);
}
// ...
}
The V-table lookup is now done on the instance of Serializable and it will find, for example, ExtFileSystemIdentifier.serialize. It can statically determine that the closest matching overload is for Serializer<T> (it just so happens to also be the only overload).
This is all well and good. It achieves the main goal of keeping the input and output data classes oblivious to the serialization class. And it also achieves the secondary goal of giving the user of the serialization classes a consistent API regardless of what sort of serialization is being done.
Imagine now that a second set of dumb data classes exist in a different project. A new serializer needs to be written for these objects. The existing Serializable interface can be used in this new project. The Serializer interface, however, contains references to the data classes from the other project.
In an attempt to generalize this, the Serializer interface could be split into three
public interface Serializer<T> {
T serialize(Serializable s);
}
public interface ProjectASerializer<T> extends Serializer<T> {
T serialize(FileSystemIdentifier fsid);
T serialize(ExtFileSystemIdentifier fsid);
// ... other data classes from Project A
}
public interface ProjectBSerializer<T> extends Serializer<T> {
T serialize(ComputingDevice device);
T serialize(PortableComputingDevice portable);
// ... other data classes from Project B
}
In this way, the Serializer and Serializable interfaces could be packaged and reused. However, this breaks the double-dispatch and it results in an infinite loop in the code. This is the part I'm uncertain about in the V-table lookup.
When stepping through the code in a debugger, the issue arises when in the data class' serialize method.
public class ExtFileSystemIdentifier implements Serializable {
public <T> T serialize(Serializer<T> serializer) {
return serializer.serialize(this);
}
}
What I think is happening is that at compile time, the compiler is attempting to select the correct overload for the serialize method, from the available options in the Serializer interface (since the compiler knows it only as a Serializer<T>). This means by the time we get to the runtime to do the V-table lookup, the method being looked for is the wrong one and the runtime will select JsonSerializer.serialize(Serializable), leading to the infinite loop.
A possible solution to this problem is to provide a more type-specific serialize method in the data class.
public interface ProjectASerializable extends Serializable {
<T> T serialize(ProjectASerializer<T> serializer);
}
public class ExtFileSystemIdentifier implements ProjectASerializable {
public <T> T serialize(Serializer<T> serializer) {
return serializer.serialize(this);
}
public <T> T serialize(ProjectASerializer<T> serializer) {
return serializer.serialize(this);
}
}
Program control flow will bounce around until the most type-specific Serializer overload is reached. At that point, the ProjectASerializer<T> interface will have a more specific serialize method for the data class from Project A; avoiding the infinite loop.
This makes the double-dispatch slightly less attractive. There is now more boilerplate code in the data classes. It was bad enough that obviously duplicate code can't be factored out to a parent class because it circumvented the double-dispatch trickery. Now, there is more of it and it compounds with the depth of the inheritance of the Serializer.
Double-dispatch is static typing trickery. Is there some more static typing trickery that will help me avoid the duplicated code?
as you noticed the serialize method of
public interface Serializer<T> {
T serialize(Serializable s);
}
does not make sense. The visitor pattern is there for doing case analysis but with this method you make no progress (you already know it is a Serializable), hence the inevitable infinite recursion.
What would make sense is a base Serializer interface that has at least one concrete type to visit, and that concrete type shared between the two projects. If there is no shared concrete type, then there is no hope of a Serializer hierarchy being useful.
Now if you are looking to reduce boilerplate when implementing the visitor pattern I suggest the use of a code generator (via annotation processing), eg. adt4j or derive4j.
Related
I just started writing java and today I read some code like this:
public interface A extends B<A>{
...
}
public interface B<E extends B<E>>{
...
}
Of course I can understand the code, but it makes me really confused. It looks like ... I used myself to create myself? How the compiler deal with it?
Yes it is astonishing what the compiler is capable of. As said by the other answer(s), generic parameters are used by reference. But there are compilations (.class) and their dependent relations. Notice: some runtime errors are caused by unsynchronized compilation, and you can store a .java file in a jar - I believe).
That juggling with self-references is often used to pass the class of a child class to a super class for restricting things (methods) to the child class.
But the same trick of cyclic behavior can be done as pure classes:
public interface Foo {
Foo ZERO = new Bar();
}
public class Bar implements Foo {
... ZERO ...
}
So the java compiler solves this chicken/egg problem.
To answer your explicit question, the compiler validates generics by checking constraints against each other, validating that the specific types in question are legal/matching the generic references. After that (for the output code) generic types are erased. This is called 'type erasure'. The explicit steps are explained here: https://docs.oracle.com/javase/tutorial/java/generics/erasure.html
But more interesting are the semantics of what you apparently encountered.
Generic types don't mean 'use to create' but rather 'regarding' (in whatever way).
Take List for instance. List<A> means 'List containing instances of class A'. For the code calling an instance of that, it means that all methods referencing the generic type will directly or indirectly regard object(s) of type A.
Any class implementing public interface B<E extends B<E>> will be required to regard themselves in that respect. The point of this might be that at a later point methods or attributes that refer to E will then yield the type implementing them. An example could be:
public interface Chainable<E extends Chainable<E>> {
public void append(E followup);
public E getNext();
}
...
public class MyLink implements Chainable<MyLink> {
public void append(MyLink l) {
...
}
public MyLink getNext() {
...
}
}
This way, it is ensured, that any class implementing Chainable will have a method taking, and one returning an object of that class, rather than just any object.
While the above alone is useful in terms of constraints I cannot see the better use of your example's public interface A extends B<A>. The reason for this is, that any class now implementing A is just guaranteed to regard A but not the implementing class itself (which would be much more useful). Example:
public class C implements A {
public A methodDeclaredInB(A someParam) {
...
}
}
The method above only knows A at compile time, but not C. If instead someone wrote:
public class C implements B<C> {
public C methodDeclaredInB(C someParam) {
...
}
}
then class C could be used instead of 'only' A.
There may be cases where it is sufficient to know type A, but usually you want type C, so making a (itself non-generic) interface A that extends B in such a way seems a fragile shortcut to the more verbose but more useful example above.
I need to add one optional method in existing abstract class that is extended by more than 50 classes:
public abstract class Animal{...}
This method is not used by all those classes, but in the future it probably will.
The structure of one of my classes is:
public class Dog extends Animal {...}
The cleanest way is using abstract method but it obliges me to change all existing classes.
The workaround is to create "empty" method in abstract class:
public String getString(Map<String, Object> params){
return "";
}
and then override it when I need in classes that extend abstract class.
Is there any better solution?
Having an "empty" method is fine. But in order to be sure, that it will be implemented where it is really needed, consider throwing an exception by default from this method:
throw new UnsupportedOperationException();
A similar approach is used in java.util.AbstractList class:
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
I can't help feeling like you have some architectural/design issues here, but without knowing more, I can't say for sure. If 50 classes are going to inherit from Animal, but not all of them are going to use this method, then I'm wondering if they should really inherit from one common class. Perhaps you need further levels of sub-classing... think Kingdom->Phylum->Sub-Phylum. But my gut says that's still not the right answer for you.
Step back - what are you trying to accomplish? If you're going to implement this function on these classes in the future, then you must also be changing your code to know to use/expect this. The point of inheritance is to allow code to refer to an object's expected common behavior without knowing what type of object it's referencing. In your getString() example, you might have a function as such:
public string SendMessage(Animal someAnimal) {
string message = someAnimal.getString();
// Send the message
}
You can pass it a dog, a cat, a platypus - whatever. The function doesn't care, because it can query the message from its base class.
So when you say you'll have animals that don't implement this message... that implies you'll have logic that ensures only cats and dogs will call this function, and that a platypus is handled differently (or not at all). That kind of defeats the point of inheritance.
A more modern approach would be to use interfaces to establish a "has a" relationship instead of an "is a" relationship. A plane might have an IEngine member, but the specific type of engine can be set at run-time, either by the plane class itself, or by the app if the member is writeable.
public interface IEngine {
string getStatus();
string getMileage();
}
public class Cessna {
public IEngine _engine;
public Cessna() {
_engine = new PropellerEngine();
}
}
You could also inherit directly from that interface... Animals that don't implement IAnimalMessage wouldn't implement that function. Animals that do would be required to. The downside is that each animal will have to have its own implementation, but since your base class currently has an abstract function with no body, I'm assuming that's a non-issue. With this approach, you can determine if the object implements the interface as such:
IAnimalMessage animalMessage = myPlatypus as IAnimalMessage;
// If your playtpus doesn't implement IAnimalMessage,
// animalMessage will be null.
if (null != animalMessage) {
string message = animalMessage.getString();
}
public interface IAnimalMessage {
string getMessage();
}
public class Platypus : IAnimalMessage {
// Add this implementation when Platypus implements IAnimalMessage...
// Not needed before then
public string getMessage() {
return "I'm a cowboy, howdy, howdy, howdy!";
}
}
That's probably the closest to what you're asking for I can suggest... classes that don't need the message won't implement that interface until they do, but the code can easily check if the interface is implemented and act accordingly.
I can offer more helpful/specific thoughts, but I'd need to understand the problem you're trying to solve better.
I have an class with a method which accepts an argument of particular type. The behavior of the method should be dependent on the specific class. For example,
public void doSomething(SomeInterface t) {
...
}
Depending on the actual class of the argument, I need the behavior to change. I need the outer class to perform an action based on the values found in T. Specifically, the outer class needs to construct a Hibernate criteria object which has restrictions which depend on the type of T, which is an implementation of a "Query" interface. The outer class is an implementation of a parameterized builder interface which constructs instances of objects which can be used to execute queries against a data store (for example, Criteria for hibernate, a SearchQueryBuilder for elasticsearch, etc). So as you can see, the problem with having t do the work is that it would require knowledge of HOW to construct these criteria which is beyond its intended purpose of just containing information about WHAT to query
It feels dirty and wrong to do something like
if (t instanceof X) {
...
} else if (t instance of Y) {
...
}
I see a couple problems here.
This requires previous knowledge about the types being passed in
The class is not "closed for modification" and will require a modification every time a new type needs to be supported.
Can someone suggest a good design pattern that can be used to solve this problem? My first thought is to use a factory pattern in combination with strategy and create instances of the class with a "handler" for a specific type. Another thought I had was to create a mapping of Class -> Handler which is supplied to the class at construction time.
Ideas appreciated.
The simplest idea would be to put the logic in the implementations of SomeInterface:
public interface SomeInterface {
public void actOnUsage();
}
public class SomeOtherClass {
public void doSomething(SomeInterface t) {
t.actonUsage();
}
}
I have a variable: Abstract a. It is a class that extends the Abstract class. However, I need to cast this Abstract variable into a more specific class variable that extends the Abstract class.
My situation: I have two classes, Class1 and Class2 that both extend the Abstract class with methods implemented in each one. I now have an Abstract class variable to work with. I do not know if it is Class1 or Class2, so I cannot simply do a (Class1) a or a (Class2) a (casting).
So how would I successfully cast this variable so that I can use the inner methods?
I was thinking along the lines of using a.getClass().getName() to determine how to cast it, but I am stuck from here on out.
Your new question appears to be asking how to dynamically cast a variable to an arbitrary type unknown at runtime. This is probably a duplicate of java: how can i do dynamic casting of a variable from one type to another? but to summarize, this is not (easily) possible, isn't recommended, and speaks to other issues in your code.
Think about it this way, what variable would you possibly be able to use to store your newly cast object? Imagine if we had a (child) cast operation in Java, that took a variable defined as a parent class, and cast it down to its child (e.g. List -> LinkedList):
public static void func(Abstract a){
???? var = (child)a;
// Do something with var?
}
Notice that 1) there's no way you could ever specify a type for var, since we don't know at runtime what type it will be; and 2) there's nothing we'd be able to do with var beyond the behavior defined in Abstract anyways, because the compiler can't predict which methods will be availible to var other than what's available to Abstract.
If you need to implement class-specific behavior, you should do so inside the class. Have an abstract method which each class has to implement, and which can do whatever you need them to do. Or, if you cannot ensure that, don't define a function that takes an Abstract as an argument; instead define however many functions that take Class1, Class2, etc. objects as parameters, like so:
Abstract method to require all child classes behave similarly
public abstract class Abstract{
/** Do the class-specific behavior you want to do currently in func */
public abstract void operation();
public static void func(Abstract a){
a.operation();
}
}
Functions only for classes that can actually handle what you want
public static void func(Class1 a){
// do something
}
public static void func(Class2 a){
// do something
}
Again, if neither of these options are viable for you (and of course, blocks of instanceof calls aren't acceptable) then I'd be willing to bet money there's something structural in the way you're using Java that's fundamentally incorrect. If you want to post a code sample of exactly what you're trying to accomplish by child-casting, perhaps we can shed some light as to what the issue is.
Leaving this here for posterity - OP's original question asked about creating new instances of an object cast as its abstract parent.
Pretty straightforward, get the object's class object, and create a new instance. For more complex constructors, see the Java documentation on creating new instances dynamically.
public class ClassVar
{
public static abstract class Abstract
{
}
public static class Class1 extends Abstract
{
}
public static class Class2 extends Abstract
{
}
/**
* Given an instance of a child of Abstract, returns a new instance
* of the same class
*/
public static Abstract newInstance(Abstract obj) throws InstantiationException, IllegalAccessException
{
return obj.getClass().newInstance();
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException
{
System.out.println(newInstance(new Class1()).getClass());
System.out.println(newInstance(new Class2()).getClass());
}
}
Result:
class ClassVar$Class1
class ClassVar$Class2
Basically you can use reflection by using
Class cl = ...
cl.newInstance()
The more 'expanded' answer you can find here
Since you edited your question again 3h ago at the time of writing here's my second answer to a problem I thought was solved. It's obvious nobody got what you're really asking for in the first place. Try to improve how you're asking questions.
However, the answer is simple:
From the point of view of object orientation you simply shouldn't have to (Liskov Substitution principle). Even if you have exact knowledge about exactly two possible instances, you should look for a better approach for the problem you are trying to model.
If you have to, determine the class name and check for equality or carry an extra identifier and compare that one. Implementation couldn't be simpler.
I have an abstract class that implements an interface. I then have several classes that extends that abstract class that are in turn composed of a hierarchy of some objects plus one or more Lists of objects extending the same abstract class, repeated for some levels. In essence,
public interface Bar
public abstract class BarImpl implements Bar
public class Foo extends BarImpl {
private String value1;
private String value2;
private List<Foo2> fooSubs;
public List<Foo2> getFooSubs() {
return fooSubs;
}
}
public class Foo2 extends BarImpl {
private String value3;
private String value4;
private List<Foo3> fooSubs;
public List<Foo3> getFooSubs() {
return fooSubs;
}
}
...etc...
The data in question is actually X12 healthcare claim data for those who are familiar. I've defined a Loop interface to correspond to the various loops that compose the X12 file.
My issues is this - I need to also be able to describe a single transaction, in theory using the same object or some wrapper on that object, where for some specified depth the size of each list of objects is 1.
My first though is/was to add a boolean singleTransaction to the BarImpl abstract class. Each class extending that would then have a check on the addFoo methods to make sure that the object did not grow beyond the single entry. Before converting to FooSingle I would check as well.
public void addFoo(Foo foo) throws FooException {
if (singleTransaction && fooSubs.size() >= 1)
throw new FooException();
else
fooSubs.add(foo);
}
I would also have to remove the setFoo method, so as to prevent an already-populated List from being assigned. Perhaps just make it final...
Does this seem like a reasonable way to go about this? I could then have a SingleBarImpl class that would verify it had a single path down the hierarchy, filter the boolean down, and could then safely assume that there was only one object-per-list for the specified classes. This could then simplify the access to the hierarchy since I no longer needed to worry about multiple list entires.
This feels very ugly is why I raise the question, and I wasn't quite sure what I should search on for an alternative. So I decided to stop lurking, create an account, and throw this out there. So...any ideas? Am I missing some design pattern that makes this much more elegant?
I am not familiar with X12 healthcare claim data and hence can't properly model the domain, but it sounds like you want to use the GOF composite pattern . A "Leaf" implementation class could easily replace your "singleTransaction" flag