2015-05-04 47 views
2

比方说,我有一个情况如下:只能使用获得的静态类型在运行时

XS类型的字段s

S由两个类AB都实施一些相同的方法/我们都知道然后应在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的),让我把这种方法。

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

+0

你可以添加一个接口到'A'和'B'吗? –

+0

设计是非常糟糕的男人!你需要改变它 – Pratik

+0

@pratik如果可能的话,我已经做到了!不幸的是,它现在必须保持这样的状态 – Demplo

回答

4

如果您可以更改AB,那么您可以向两者添加相同的接口。这将允许您将此类型设置为downcast_field并调用方法。

如果你不能改变AB,那么你有两种选择:

  • 你可以写A2B2。将代码从AB复制到新的类型中。这允许您修改代码(除非您无法控制这些类型的创建)。或者,您现在也可以创建S2,它扩展了S并将通用代码放在那里,然后从中扩展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(); 
    

    可以使两个包装延长相同类型的并且有移动通用代码。

+0

我喜欢委托包装类的使用,除了它为了这个目的添加了另外三个具有'A'和'B'特定知识的类,这是一种马虎。鉴于这种情况,我认为这几乎是最好的可用解决方案(除了Java 8中的东西,但有可能你没有使用该解决方案) –

+0

是的,你可以使用方法引用,关闭或反射。引用应该很快,关闭应该没问题,反射会很慢。 –

+0

用midClass扩展S是我最初的想法。总的来说,我认为在任何情况下都不可能有任何优雅的解决方案。感谢少数的可能性。 @ShotgunNinja的机会是正确的,没有java8: - / – Demplo

3

据我了解,您的情况如下?

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; 
    } 
} 
相关问题