【问题标题】:Use a static type only obtainable at runtime使用只能在运行时获得的静态类型
【发布时间】:2015-05-04 13:55:17
【问题描述】:

假设我有如下情况:

一个类X 有一个s 类型为S 的字段。

SAB 两个类扩展,它们都实现了一些我们都知道应该在 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 之外),它允许我调用这些方法。

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

【问题讨论】:

  • 可以给AB添加接口吗?
  • 这个设计很糟糕的人!你需要改变它
  • @pratik 如果可能的话,我早就这么做了!不幸的是,它必须暂时保持这种状态
  • 你在哪个班级使用上面的代码?理想情况下,A 或 B 可以使用 S 本身来表示
  • 在X类中,字段为S类型。

标签: java inheritance instanceof dynamic-cast static-typing


【解决方案1】:

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

如果您无法更改AB,那么您有两种选择:

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

    您可以使两个包装器扩展相同的类型并将公共代码移到那里。

【讨论】:

  • 我喜欢使用委托包装类,除了它添加了另外三个具有AB 的特定知识的类只是为了这个目的,这有点草率。鉴于这种情况,我认为这几乎是最好的可用解决方案(除了 Java 8 中的东西,但你很可能没有使用它......)
  • 是的,您可以使用方法引用、闭包或反射。引用应该很快,闭包应该没问题,反射会很慢。
  • 用 midClass 扩展 S 是我最初的想法。总的来说,我认为在任何情况下都不可能有任何优雅的解决方案。感谢您提供的一些可能性。 @ShotgunNinja 机会是正确的,没有 java8:-/
【解决方案2】:

据我了解您的情况如下?

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;
    }
}

【讨论】:

    猜你喜欢
    • 2023-02-23
    • 1970-01-01
    • 1970-01-01
    • 2017-09-26
    • 1970-01-01
    • 2014-11-09
    • 1970-01-01
    • 2013-04-13
    • 2016-04-19
    相关资源
    最近更新 更多