【问题标题】:Generic method that accept only part of classes只接受部分类的通用方法
【发布时间】:2012-12-21 12:44:49
【问题描述】:

假设我有以下类结构:

class Base {}
class A extends Base {}
class B extends Base {}
class C extends Base {}

我想编写一个方法,它接受 AB 的实例,但不接受 C 的实例。
我可以用Java实现吗?

我知道这不是很好的继承情况(AB 应该有不同于 C 的共同父级),但我只是好奇是用 Java 的方式来处理这样的情况。

编辑:
!!!
我知道更好的继承会解决问题。我只是好奇,如果 Java 有一些标准机制来解决这样的问题。
!!!

【问题讨论】:

    标签: java generics inheritance


    【解决方案1】:

    使用interface 并且只有AB 实现它。

    【讨论】:

      【解决方案2】:

      你可以使用接口吗?例如

      class Base {}
      interface MyGenericInterface {}
      class A extends Base implements MyGenericInterface {}
      class B extends Base implements MyGenericInterface {}
      class C extends Base {}
      

      这样,该方法可以接受 MyGenericInterface 的实现,并且由于 A 和 B 实现了接口而 C 没有实现,因此它会根据需要接受 A 和 B 的实例而不是 C。

      【讨论】:

        【解决方案3】:

        您可以在运行时使用异常处理它:

        void genericMethod(Base arg_in)
        {
            if(arg_in instanceof C)
            {
                throw IllegalArgumentException("C class not accepted."); 
            }
        
            ...
            ...
        }
        

        【讨论】:

          【解决方案4】:

          如果某些东西应该接受AB 而不是C,那么你应该重新考虑为什么C 首先继承自Base。您可以添加额外的继承层:

             ---Base---
             |        |
          --Sub--     C
          |     |
          A     B
          

          然后你可以让你的方法只接受Sub类型的对象。 Sub 甚至不需要做任何事情,从技术上讲,它们都是 Base

          一个更快的解决方案将是一个肮脏的if( arg.instanceof(C) )虽然......

          【讨论】:

            【解决方案5】:

            不应该仅仅因为你想要这样的方法而改变类型层次结构。 但是,如果您希望使用这种方法,则可能表明您应该考虑一下您的 类型层次结构。

            但如果你确定你的类型设计得很好,那么这种方法呢:

                public class T {
            
                    public void doSomething(final A a) {
                        doSomthing(a);
                    }
            
                    public void doSomething(final B b) {
                        doSomthing(b);
                    }
            
                    private void doSomthing(final Base b) {
            
                        // Here is the implementation
            
                    }
            
                }
            

            【讨论】:

            • 我不知道您在此处使用 final 关键字的目的是什么,但它不会阻止在呼叫站点发生扩大的转换。由于C 的每个实例都是B 的实例,因此始终可以将C 的实例传递给您的doSomething() 方法。
            • 您为什么认为“C 是 B 的实例”? A,B,C 都只扩展 Base
            • 'final' 与功能无关。只是我习惯的编码约定。
            • 嗯...重新审视这个问题,我似乎误读了这个问题。我很抱歉。
            【解决方案6】:

            我猜您的问题的答案是“不,java 没有处理此类问题的标准方法”。如果您有这个问题,那么您可以在这里查看其他答案,例如修复继承或使用巧妙的技术given by MrSmith42

            【讨论】:

            • @MichałHerman 对吗? 17 - 1 ... 天哪,这就像在工作。
            • @NimChimpsky 别担心,这类事情有徽章。 :)
            • 是的,对我来说这个答案是正确的,因为我问如果 Java 有一些构建机制来处理这类问题。不是我自己如何处理这类问题,因为我已经知道了。
            【解决方案7】:

            您可以使用instanceof 来检查对象是否属于某种类型。

            当然,更好的想法是更好的继承结构。

            【讨论】:

            • 明确一点:在 Java 中,instanceof 适用于子类。也就是说,C c = new C(); c instanceof B 将返回 true。如果要排除C,则需要明确检查。 (添加评论是因为乍一看这个答案我并不清楚。)
            【解决方案8】:

            泛型是为了类型安全。时期。不要“允许”或“禁止”任意事情。没有类型安全的理由允许 A 和 B 而不是 C。

            【讨论】:

              【解决方案9】:

              试试下面的sn-p

              public <T extends Base> void setAuditorDetails(T model) 
              {
                       if(!(T instanceof C)){
              
                            // Your Business logic
              
                       }
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2020-09-14
                • 2013-06-22
                • 1970-01-01
                • 2019-08-28
                • 1970-01-01
                • 1970-01-01
                • 2015-03-09
                相关资源
                最近更新 更多