Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用只能在运行时获得的静态类型_Java_Inheritance_Instanceof_Dynamic Cast_Static Typing - Fatal编程技术网

Java 使用只能在运行时获得的静态类型

Java 使用只能在运行时获得的静态类型,java,inheritance,instanceof,dynamic-cast,static-typing,Java,Inheritance,Instanceof,Dynamic Cast,Static Typing,假设我的情况如下: 类X具有类型为s的字段s S被两个类A和B扩展,这两个类都实现了一些我们都知道应该在S中实现的相同方法/字段,但不幸的是,情况并非如此 现在我想做这样的事情: "A or B" downcast_field; if(s instanceof A) downcast_field = (A)s; else if (s instanceof B) downcast_field = (B)s; //do something common for the two c

假设我的情况如下:

X
具有类型为
s
的字段
s

S
被两个类
A
B
扩展,这两个类都实现了一些我们都知道应该在
S
中实现的相同方法/字段,但不幸的是,情况并非如此

现在我想做这样的事情:

"A or B" downcast_field;
if(s instanceof A)
    downcast_field = (A)s;
else if (s instanceof B)
     downcast_field = (B)s;

//do something common for the two cases but that need methods implemented both in A and B
问题是预先有一个静态类型(在
IFs
中),允许我调用这样的方法


我想,由于糟糕的设计,这实际上是不可能的,我必须编写两次相同的代码,这很难看,但也许有一个解决方案我现在没有看到。

如果您可以更改
a
B
,那么您可以将相同的接口添加到两者。这将允许您将此类型赋予
downcast\u字段
并调用方法

如果无法更改
A
B
,则有两个选项:

  • 您可以编写
    A2
    B2
    。将
    A
    B
    中的代码复制到新类型中。这允许您修改代码(除非您无法控制这些类型的创建)。或者,您现在还可以创建扩展
    S
    S2
    ,并将公共代码放在其中,然后从中扩展
    A2
    /
    B2

  • 创建一个接口,然后创建两个实现,将调用委托给实际类型

    在这个解决方案中,您可以

    Wrapper downcast_field;
    if(s instanceof A)
        downcast_field = new AWrapper( (A)s );
    else if (s instanceof B)
        downcast_field = new BWrapper( (B)s );
    
    downcast_field.foo();
    
    您可以使两个包装器扩展相同的类型,并将公共代码移到那里


    • 据我所知,您的情况如下

      public class S {
      }
      
      public class A extends S {
      
          public void doSomething() {
              System.out.println("A is doing something ...");
          }
      }
      
      public class B extends S {
      
          public void doSomething() {
              System.out.println("B is doing something ...");
          }
      }
      
      实际上我觉得这个设计很糟糕。如果你有机会 清理干净,你应该这样做。如果这不是一个选项,请执行以下操作 解决方法是可能的。。。引入一个声明公共API的接口 并使用此接口包装您的实例

      public interface WrapperInterface {
          void doSomething();
      }
      
      那么你可以这样用这个

      public class Main {
      
          public static void main(String[] args) {
              WrapperInterface a=wrap(new A());
              WrapperInterface b=wrap(new B());
      
              a.doSomething();
              b.doSomething();
          }
      
          private static WrapperInterface wrap(final S s) {
              WrapperInterface downcast_field=null;
              if (s instanceof A)
                  downcast_field = new WrapperInterface() {
                      @Override
                      public void doSomething() {
                          ((A) s).doSomething();
                      }
                  };
              else if (s instanceof B) {
                  downcast_field = new WrapperInterface() {
                      @Override
                      public void doSomething() {
                          ((B) s).doSomething();
                      }
                  };
              }
              return downcast_field;
          }
      }
      

      你能给
      A
      B
      添加一个界面吗?这个设计太糟糕了!你需要改变it@pratik如果可能的话,我早就这么做了!不幸的是,它必须一直保持这样的状态,您在哪个类中使用上述代码?理想情况下,A或B可以用S本身在类X中表示,字段的类型为S。我喜欢使用委托包装类,除了它添加了另外三个具有
      A
      B
      特定知识的类,只是为了这个目的,这有点草率。考虑到这个场景,我认为这几乎是最好的解决方案(除了Java8中的东西,但很可能您没有使用它…)是的,您可以使用方法引用、闭包或反射。引用应该很快,闭包应该很好,反射会很慢。用中产阶级扩展S是我最初的想法。总的来说,我认为在任何情况下都不可能有任何优雅的解决方案。谢谢你给我这么多的可能性@Shotgunnija的机会是正确的,没有java8:-/