例如,假设我:
class Gundam00 extends Gundam implements MobileSuit {
...
public void fight(final List<MobileSuit> mobiruSuitso, final List<Gundam> theOtherDudes, final List<Person> casualities) {
....
}
}
假设其他人和伤亡参数是可选的。如何使此方法尽可能干净?我想过让布尔指出它们是否为空,然后根据需要进行检查。
对于每个参数组合,我也可以使用不同版本的方法,但我认为会有很多代码重复。
有什么建议吗?
答案 0 :(得分:3)
我发现过去的2-3个参数,能够记住函数的所有参数都会受到影响。并且可以理解。
传递命名参数可以提供帮助。具有类似哈希的文字语法的语言使这非常简单。拿JavaScript:
g = new Gundam00();
g.fight({opponent: enemy, casualties: 'numerous'});
您还可以利用可变长度参数功能来处理此问题(将奇数参数视为名称,甚至将参数视为实际参数)。
g.fight('opponent',enemy,'casualties', 'numerous');
有些语言实际上直接支持命名参数(参见:http://en.wikipedia.org/wiki/Named_parameter#Use_in_programming_languages)。
最后,您可能需要考虑使用一些调用Fluent接口(http://en.wikipedia.org/wiki/Fluent_interface)来添加其他方法。基本上,你有方法调用返回对象本身,所以你可以一起链接调用:
g.opponent(enemy).casualties('numerous').fight();
如果您使用明显/静态类型的以类为重点的语言,这可能是最简单的选择。
更新
回应Setsuna的评论......在最后一个例子中,如果你有奢侈的话,你可以制作像opponent
和casualties
这样的方法,这些方法不会影响任何内部状态或以任何其他方式计算,而不是设置它们被命名的参数。他们只是设置内部属性,然后所有实际工作都在fight
等动作方法中进行。
如果你不能这样做(或者如果你不喜欢编写操作是亚原子的方法),那么你可以在这个想法与类似哈希的文字理念之间找到一个中间点,并创建你自己的集合类专门用于调用命名参数:
n = new NArgs();
g.fight(n.arg('opponent',enemy).arg('casualties','numerous').arg('motion','slow'));
稍微笨拙一点,但是它将命名参数问题分开并允许你保持你的方法更加原子化,并且NArgs可能很容易实现,只需围绕一种类型的Collection(HashTable?)包装一些方法或其他以您的语言提供的。
答案 1 :(得分:2)
添加方法。重载方法通常是反模式和其他人的重构机会。
http://www.codinghorror.com/blog/2007/03/curlys-law-do-one-thing.html
答案 2 :(得分:0)
我想过让布尔表示他们是否为空,然后检查它们并做出相应的反应。
或者......你可以检查它们是否为空。
if(theOtherDudes == null)
...
答案 3 :(得分:0)
如果您的类中只有一个“main方法”,那么您可以将可选参数实现为getter / setter函数。例如:
public void setOtherDudes(final List<Gundam> theOtherDudes) {} // for input arguments
public List<Person> getCasualities() {} // for output arguments
然后,在您的文档中,请注意,如果调用者有任何可选的输入参数,则必须在调用fight()
之前传入它,并且fight()
时可选输出值可用调用。
如果有许多可选参数,这是值得的。否则,我建议将方法重载为最简单的方法。