我有一个非常常见的模式“给定Foo
,返回Bar
”,例如,给定user_id
,返回User
。
这些功能是否有传统的命名模式?在Joel on Software之后,我个人使用了很多bar_from_foo()
,但我很少看到其他人这样做,很快就会变得冗长,例如。
widgets = user_widgets_from_user(user_from_param_map(params))
是否有传统的方式来命名或命名空间(例如User.from_map()
)在任何流行的语言?我对Python特别感兴趣,但你能想到的任何语言都会很有用。
答案 0 :(得分:15)
我会利用Clojure的命名灵活性并将其命名为:
(defn foo->bar [] ...)
对我来说,这意味着很明确,而且很短。
答案 1 :(得分:5)
如果要将某些东西转换为另一个,例如字符串为整数,则该方法将在接收器上定义,因此其类是明确的,因此您不应将接收器类作为方法的一部分名称:String#to_i
,而不是String#string_to_i
。这是面向对象编程(多态)的核心思想之一。
如果接收者过于笼统而无法分配此类方法,例如,如果user_id
仅仅是字符串,并且在String
上定义方法以将其转换为User
则不会看起来正确,那么你应该在类上定义一个你希望返回值为:User.new
或User.from_id
的构造函数方法。
答案 2 :(得分:5)
在Python和其他各种OO语言中,这应该是Bar上的构造函数,它将单个Foo作为唯一参数。由于Python不进行方法重载(并且尝试模拟它通常很脆弱),如果Bar.__init__
已经采用不同的签名,那么约定就是最后一个。重要的是,这通常被定义为类方法而不是静态方法(为了子类的利益):
class Bar:
@classmethod
def from_foo(cls, f):
'''Create a new Bar from the given Foo'''
ret = cls()
# ...
答案 3 :(得分:3)
我认为这很大程度上取决于背景并选择一个有意义的比喻。例如,ActiveRecord使用类方法“find”来查找数据库中的记录,这比“输入user_id,输出用户”更有意义。例如:
User.find(user_id)
User.find_by_email(user_email)
对于转换,我通常喜欢编写转换方法,以便在高阶函数中使用。例如,在ruby中,转换通常使用to_*
实例方法完成,例如将Foo
转换为Bar
,为所有人设置to_bar
方法是有意义的foos,所以你可以写:
foo = Foo.new(...) # make a new Foo
bar = foo.to_bar # convert it to a Bar
然后转换一堆foos,你可以简单地说:
bars = foos.map(&:to_bar)
Ruby也倾向于Foo.parse(str)
将字符串转换为对象。
对于javascript,我喜欢使用类方法(我从标准ml获得),例如:
Foo.toBar = function(foo) {
return new Bar(...);
};
然后你也可以在它上面映射(在这个例子中使用下划线):
var bars = _.map(foos, Foo.toBar);
标准ML约定是结构(类)方法。示例fn类型:
Foo.toBar : foo -> bar
Foo.fromBar : bar -> foo
你会像以下一样使用它:
val bar = Foo.toBar foo;
val bars = map Foo.toBar foos;
答案 4 :(得分:1)
为什么将参数的类型放在函数名称中?我认为会更清楚像
a_bar = bar_from(a_foo)
然后你可以依赖于许多语言的动态调度或重载......例如在Python中,如果存在,实现可能会尝试调用x.toBar()
,或者它可以检查像Bar_builders[type(x)](x)
这样的全局注册表;在Lisp中你可以依赖方法;在C ++中重载...