【问题标题】:Returning object depending on a value in a generic way以通用方式根据值返回对象
【发布时间】:2018-05-31 09:35:33
【问题描述】:

考虑到我有很多类,都继承自同一个类

public class A
{
  ...
}

public class AA extends A
{
  ...
}

public class AB extends A
{
  ...
}

public class AC extends A
{
  ...
}

然后在代码的其他部分,我想返回一个子类,具体取决于发送到该函数的值,如下所示:

public A getChild(int value, Object foo)
{
    switch(value)
    {
        case 0: {
            return new AA(foo);
        }
        case 1: {
            return new AB(foo);
        }
        case 2: {
            return new AC(foo);
        }
        default: {
          return new AA(foo);
        }
    }
}

在这个例子中,我只有 3 种类型的孩子。但我可以假设其中有 30 个,switch 声明会变得很大。

有没有什么方法可以使用 switch 语句之外的其他东西来做同样的事情,而且会更通用?像 C 中的函数指针一样?

【问题讨论】:

  • 好吧,您不会遇到类似if-else 行为的部分,因为您必须决定返回哪个value 哪种类型的实例

标签: java inheritance switch-statement generic-programming


【解决方案1】:

您可以使用整数值到功能接口的映射来创建A 的各种子类的实例:

Map<Integer,Function<Object,A>> map = new HashMap<>();
map.put(0,f -> new AA(f));
map.put(1,f -> new AB(f));
...

然后使用如下映射:

public A getChild(int value, Object foo) {
    return map.getOrDefault(value, f -> new AA(f)).apply(foo);
}

【讨论】:

  • 看起来不错!我需要在我的代码中更改一些东西,然后我会实现它并让你知道。谢谢:)
  • 在极少数情况下建议使用Function&lt;? super Object, ? extends A&gt; 而不是Function&lt;Object,A&gt;
  • @Eran 我有一个问题的想法。如果子类有多个参数怎么办?
  • @souki 这个解决方案目前只支持一个参数。如果你想要多个参数,你可以使用Map&lt;Integer,Function&lt;Object[],A&gt;&gt; 并让每个构造函数接受一个对象数组,但这越来越难看。或者,如果所有子类都采用多个相同的参数,您可以使用不同的函数式接口而不是 Function,以支持所需的尽可能多的参数。
  • 好吧,是的,你是对的,它会变得丑陋。希望他们都有相同的论点,所以使用不同的功能接口似乎符合我的需要。再次感谢
【解决方案2】:

在 java 中,C 中有类似的函数指针概念。 您可以使用 Java 反射(但效率不高):

public A getChild(String className, Object foo)
{
   Class c = Class.forName(className);
   return (A) c.newInstance(Object foo);
}

您可以使用 Map 来保持“int value”和“String className”之间的关联。 但是这个解决方案效率不高! 相反,您可以使用 Eran 建议的功能图。

【讨论】:

  • 感谢您的建议! :)
  • 您有一些checked 异常需要注意
  • newInstance() 不接受任何参数。
猜你喜欢
  • 2015-09-01
  • 2019-10-09
  • 2020-09-27
  • 2021-04-09
  • 1970-01-01
  • 1970-01-01
  • 2019-02-09
  • 1970-01-01
  • 2018-06-16
相关资源
最近更新 更多