【问题标题】:Most specific subclass for a Java object?Java 对象的最具体的子类?
【发布时间】:2009-05-17 14:10:21
【问题描述】:

我有两个类 A 和 B,其中 B 是 A 的子类,A 不是抽象的。因此,我可以拥有作为 A 实例的对象和作为 B 实例的对象(因此也是 A 的实例)。

如何区分仅是 A 实例的对象?

当然,我可以写类似“object instaceof A && !(object instance of B)”,但这是一个非常糟糕的设计,因为每次向 A 添加新的子类时我都需要更改代码。更好的选择?

【问题讨论】:

    标签: java inheritance instanceof


    【解决方案1】:
    object.getClass() == A.class
    

    【讨论】:

      【解决方案2】:

      为什么要他们区分?通常这与 OO 相反。你有不同的实例,你不需要区分,因为不同的实现做的一切都是正确的。

      如果您需要这样做,那么应该有一个协议。为此目的,有一个方法可以返回要识别的东西。这也更灵活。

      如果没有正当理由使用它,我会认为 instanceOf 和 getClass 的样式不好

      【讨论】:

      • +1 你的回答。 Java 是一种静态语言,如果您必须考虑对象的动态类型,请查看访问者模式。
      • 这看起来像是要以非常OO的方式解决的Dispatcher模式的情况。该模式支持依赖于对象类型的不同行为,但我不确定在 Java 中是否可能。恕我直言,语言需要更好地支持元编程......
      【解决方案3】:

      更好的方法是让测试成为方法的结果

      class A {
         public boolean isSomeTest() {
            return true;
         }
      }
      class B extends A {
         public boolean isSomeTest() {
            return false;
         }
      }
      

      然后,如果您添加一个扩展 A 的 C,您可以允许它返回 true 或 false。

      isSomeTest 的名称应该明确返回 true 或 false 的含义。

      【讨论】:

        【解决方案4】:

        这就是我认为你在说的:

        public class A {
        }
        
        public class B extends A {
        }
        

        稍后在代码中:

        A apple = new A();
        B banana = new B();
        

        以下是一些您可能会觉得有用的选项:

        if (apple.getClass() == A.class) { // Found an A }
        if (banana.getClass() == A.class) { // This is not an A, won't get here. }
        if (apple instanceof A) { // This is definitely an A }
        if ((apple instanceof A) && (!(apple instanceof B))) { // It's an A but not a B }
        

        关于最后一个选项,你写如下:

        当然,我可以写类似的东西 “对象实例 A && !(对象 B)的实例”,但这是一个非常 糟糕的设计,因为我需要改变 每次我添加新的代码 A 的子类。更好的选择?

        多态性几乎总是在这里帮助我们。您关于每次添加子类时更改代码的观点正是您应该认识到的标准面向对象设计演变的症状。想想你试图产生的行为。您能否将其推送到课程本身,而不是将其委托给外部提供者,该提供者查看必须推断其当前正在处理的课程?

        如果没有更多信息,我无法提供太多指导,但这里有一个相当简单的示例:

        // Instead of this
        if (apple.isClassA()) { // run class A code
        } else if (apple.isClassB()) { // run class B code
        // And so forth
        }
        

        修改设计,使其更像这样:

        public class A {
            public void executeCommand() { 
                // run class A code 
                // This method knows that it's definitely an A, not a B
            }
        }
        
        public class B extends A {
            public void executeCommand() { 
                // run class B code 
                // This method knows that it's a B (and, therefore, an A as well).
            }
        }
        

        稍后在执行代码中,您将之前的 if 测试替换为:

        apple.executeCommand();
        banana.executeCommand();
        

        诚然,这是一个几乎微不足道的面向对象设计审查,但它可能会动摇一些东西并帮助您解决子类化问题。

        【讨论】:

        • 为什么香蕉是苹果的子类?
        • 是的,这是一个有趣的想法,诚然。也许我正在尝试在树上对不同种类的儿童果汁盒进行基因工程。我试图避免“A 级”和“A theA”的“标准”可怕组合;或“AAAA”;相反,A 代表苹果,B 代表香蕉。如果你能想到各种以 B 开头的苹果,我就改一下。
        【解决方案5】:

        这不是表明 B 不是真正的 A 吗? 我不完全确定你应该进入这种情况吗?也许你可以改进你的设计??

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-04-25
          • 2018-12-12
          • 2023-03-27
          • 1970-01-01
          • 1970-01-01
          • 2021-05-25
          • 1970-01-01
          相关资源
          最近更新 更多