简体   繁体   中英

Need to determine type of object at runtime Java. Bad design?

I am writing a particle transport code. In this code physical objects implement an interface Volume. One implementer of Volume is the case of interest for this code-- the Particle class. In my design, Volumes contain other Volumes all the way down to the smallest Volume implementer, Particle. This will work great as long as Particles want to fly around unmonitored through volumes having interactions.

However, the moment I want to implement some sort of Particle detector Volume, which will record information about the Particle, I have a problem. The Volume interface doesn't contain a way to get the special type of information a Particle has. If a Particle makes its way into the detector Volume, I will have to do something like check its type with reflection before I cast it to Particle from Volume and call the Particle methods. Generally (from what I have seen) this type of thing gets flagged with a "bad design" label.

I could make it so that only Particles can cross Volume boundaries in the Volume interface (tie the interface to the special case Particle), but I don't really want to impose that limit on my code. It's possible that I may want to allow volumes to move around and join later.

So does this sound like a bad design? Is there another obvious way to handle this problem? I will attach code if need be, but the general problem seems independent of my particulars (and fairly independent of language).

Thanks in advance. I really appreciate all the knowledge here on SO.

From what I've read, dynamic casting is not considered terrible in Java. Simple type checking is much less extreme than using the full Reflection API.

You can either attempt the dynamic cast and catch a possible ClassCastException , or do an isinstance Particle check before casting.

Conceptually, it may make more sense for Particles to implement an interface that indicates they have the information your Particle detector wants to record. Without knowing more about your design we can't say.

Sounds to me like particles aren't really a volume because volumes can contain other volumes and particles can't do this. This violates the Liskov Subsitiution Principle . You should consider not having the particles inherit from the Volumes interface and instead inherit from something else.

If one does not have control over all the types that might be stored in a reference, and if some of the types are going to have capabilities that others lack, the most practical approach may be to define interfaces for the capabilities in question, check whether a object implements desired interfaces, and cast the object if it does. If one does have control over the types, however, other approaches might be better.

For example, if an application has a collection of objects that all inherit from a common base type which is unique to that application, and a new object type needs to be notified when something happens, one could define an interface for such notification and have the application loop through all objects and send notifications to those that implement the interface, but one could also add to the base type a no-nothing "notify" method to the base type and invoke that method upon all the objects in the collection. It may be good to also have a method to test whether the notification is necessary (to allow the application the option of maintaining a collection that only contains objects requiring such notification), but in many cases calling a do-nothing method will be simpler and more efficient than testing whether a method needs to be called.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM