简体   繁体   English

需要在运行时Java确定对象的类型。 糟糕的设计?

[英]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. 在此代码中,物理对象实现了接口Volume。 One implementer of Volume is the case of interest for this code-- the Particle class. Volume的一个实现者是这个代码感兴趣的例子 - Particle类。 In my design, Volumes contain other Volumes all the way down to the smallest Volume implementer, Particle. 在我的设计中,Volumes包含其他Volumes一直到最小的Volume实现者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. Volume接口不包含获取Particle所具有的特殊信息类型的方法。 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. 我可以做到这一点,只有粒子可以跨越Volume接口中的Volume边界(将接口绑定到特殊情况粒子),但我真的不想对我的代码施加限制。 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. 我非常感谢SO的所有知识。

From what I've read, dynamic casting is not considered terrible in Java. 从我所读到的,动态转换在Java中并不算糟糕。 Simple type checking is much less extreme than using the full Reflection API. 简单类型检查远不如使用完整的Reflection API。

You can either attempt the dynamic cast and catch a possible ClassCastException , or do an isinstance Particle check before casting. 您可以尝试动态强制转换并捕获可能的ClassCastException ,也可以在强制转换之前执行isinstance Particle检查。

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 . 这违反了Liskov Subsituiution Principle You should consider not having the particles inherit from the Volumes interface and instead inherit from something else. 您应该考虑不让粒子继承自Volumes接口,而是从其他东西继承。

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. 例如,如果一个应用程序有一个对象集合,这些对象都是从该应用程序所特有的公共基类型继承的,并且当某些事情发生时需要通知新的对象类型,那么可以为这种通知定义一个接口并拥有应用程序循环遍历所有对象并向实现该接口的那些对象发送通知,但是也可以向基类型添加基本类型的无任何“notify”方法,并对集合中的所有对象调用该方法。 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. 最好还有一种方法来测试通知是否必要(允许应用程序选择维护只包含需要此类通知的对象的集合),但在许多情况下,调用无操作方法将更简单,比测试是否需要调用方法更有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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