我试图通过应用单一责任原则来减少我的胖模型.我正在将很多常用代码剔除到mixins中,然后将它们包含在多个类中.但是,我遇到了这个局部变量与包含mixin的类的方法名(或attr_accessors)冲突的奇怪问题.例如:
module MyAwesomeMixin
def update_total
my_total = self.pricing_items.reduce(0) {|sum, x| sum + x} # this borks if the "host class" has a method called my_total=
total = my_total
end
end
Run Code Online (Sandbox Code Playgroud)
如果"主机类"有一个名为" my_total=如何确保my_total变量完全在update_total方法范围内并且与周围环境完全无关" 的方法,则上面的代码片段会产生完全意想不到的后果?
只要局部变量和方法解释之间存在歧义,它就会被解释为局部变量.
但是,除了方法定义之外,局部变量将不可用,因此您无需担心"主机类"中的名称崩溃.您只需要在您的方法定义中担心它update_total.由于您在定义中使用了固定数量的局部变量,因此您应该能够知道要注意哪些变量.
1.局部变量和setter方法之间的歧义
如果你有这个:
variable_name =
Run Code Online (Sandbox Code Playgroud)
然后它将始终被解释为局部变量赋值.如果要引用该方法variable_name=,则需要使用明显的接收器和/或一对括号来消除它与局部变量的歧义,如下所示:
self.variable_name = foo
variable_name=(foo)
self.variable_name=(foo)
Run Code Online (Sandbox Code Playgroud)
2.局部变量和getter方法之间的歧义
如果你有:
variable_name
Run Code Online (Sandbox Code Playgroud)
并且范围中没有这样的局部变量,那么它将被解释为方法调用.如果范围中有这样的局部变量,那么它将被解释为局部变量.如果要在这种情况下调用该方法,则需要使用显式接收器和/或一对括号(如下所示)将其从局部变量中消除歧义:
self.variable_name
variable_name()
self.variable_name()
Run Code Online (Sandbox Code Playgroud)
有些东西你没有告诉我们.在这种情况下,唯一的"无意义后果" my_total=是不调用该方法,因为my_total创建了本地var .
module MyAwesomeMixin
def update_total
my_total = 10 # !> assigned but unused variable - my_total
end
end
class Foo
include MyAwesomeMixin
attr_accessor :my_total
end
f = Foo.new
f.my_total # => nil
f.update_total
f.my_total # => nil
Run Code Online (Sandbox Code Playgroud)
如果您打算拨打设定者,请将其打开self.
module MyAwesomeMixin
def update_total
self.my_total = 10
end
end
f = Foo.new
f.my_total # => nil
f.update_total
f.my_total # => 10
Run Code Online (Sandbox Code Playgroud)