基本上我想要的是两种具有稍微不同的返回值的公共方法,以调用相同的方法来完成所需的任何工作。它们都返回私有方法的返回值,但私有方法将知道如何根据调用它的公共方法返回正确的值。
示例方法:
public Map<Type1, Type3> doSomething1();
public Map<Type2, Type3> doSomething2();
private Map<Type1/Type2, Type3> doSomething();
因此,在上面的示例中,doSomething()返回Type1或Type2作为Map的键类型,具体取决于调用它的公共方法。它可以执行简单的检查,并使用正确类型的对象填充地图。
也许这可以通过一些聪明的Java反射来完成?我不确定。这一切看起来都很狡猾,所以如果有更好的方法可以解决这个问题,我会全力以赴。
答案 0 :(得分:8)
我强烈建议在这里避免使用反射魔法。一个函数必须在属性上做一件事,而且不能依赖于谁调用它。
更好的方法是将doSomething()重构为更小的函数,创建两个名为doSomethingFor1()和doSomethingFor2()的新函数。这两个函数都可以重用旧的doSomething()的重构部分。
现在有doSomething1()调用并使用doSomethingFor1()。
同样,doSomething2()应该使用doSomethingFor2()。
欢呼声,
JRH。
答案 1 :(得分:3)
请注意: 我误解了这个问题,所以这个答案与问题的答案相反。我将把它留作社区维基作为参考,但这不能回答原来的问题。
如果Type1
和Type2
的公共子类型名为SuperType
,则说第一种类型为? extends SuperType
会有效。
以下是一个使用Integer
和Double
作为两种类型的示例,以及它们的共同祖先Number
:
private Map<Integer, String> doSomethingForInteger() {
HashMap<Integer, String> map = new HashMap<Integer, String>();
map.put(10, "Hello");
return map;
}
private Map<Double, String> doSomethingForDouble() {
HashMap<Double, String> map = new HashMap<Double, String>();
map.put(3.14, "Apple");
return map;
}
public Map<? extends Number, String> doSomething(boolean b) {
if (b)
return doSomethingForInteger();
else
return doSomethingForDouble();
}
此处,doSomething
方法将返回两种类型的HashMap
,具体取决于传入的boolean
。返回HashMap<Integer, String>
或HashMap<Double, String>
通过doSomething
方法。
实际上使用doSomething
调用boolean
可以这样完成:
Map<? extends Number, String> map1 = doSomething(true);
Map<? extends Number, String> map2 = doSomething(false);
map1
将以Hashmap<Integer, String>
结束,而map2
将获得Hashmap<Double, String>
。
答案 2 :(得分:1)
如果其他所有方法都失败了,那么让私有方法返回Object并在公共方法中使用强制转换。
答案 3 :(得分:1)
第一个问题是为什么你需要这个确切的结构。
但安全的方法是让它回归
public Map<Object, Type3> doSomething();
如果Type1和Type2没有常见的超类型。如果你有一个共同的超级类型,你可以使用它而不是对象。
最好重构不需要的代码。
答案 4 :(得分:1)
我需要你的问题中缺少一些信息,例如如何实例化type1和type2,因为你不能直接从任意类型参数实例化。现在,我们假设有一些常用数据用于实例化type1和type2。否则,没有充分的理由为两者使用一种方法。在后一种情况下,这意味着一个函数根据类型执行两个单独的操作,这是错误的编程。如果您将拥有直接基于调用方法的逻辑,只需使用两个私有方法并重构常见的东西。
如果仅根据某些数据进行不同的实例化,最简单的方法是声明私有内部接口:
private interface Instantiator<T> {
T getNew(Data data);
}
现在,假设您可以实例化您的类型,您实际上可以使用它:
private <T> Map<T,Type3> doSomething(Instantiator<T> instantiator) {...}
作为方法签名,并让公共方法使用适当的Instantiator实现调用它。
答案 5 :(得分:0)
你绝对可以通过使用反射分析堆栈来实现。但我会尽量避免它,并且:
答案 6 :(得分:0)
你可以模拟闭包的想法:
interface MappingClosure {
public void map(Map, MapProvider);
}
class Caller implements MappingClosure {
public void map(final Map MAP, final MapProvider CALLEE) {
this.MAP = specialise(MAP);
// CALLEE USED AS KEY
}
}
class MapProvider {
public Map getMap(final MappingClosure CALLER) {
return CALLER.map(mapInstance, this);
}
}
然后修改数据以满足对象的需要与具有需要它的对象的方法不同。