我有时会使用这个结构:
class Test
def today
date = Date.today
def date.is_friday?
strftime("%A") == "Friday"
end
date
end
end
它运作正常......
t = Test.new
t.today # => <Date: 2016-09-03 ((2457635j,0s,0n),+0s,2299161j)>
t.today.is_friday? # => false
我一直认为这是一种嵌套方法。但其他人坚持认为Ruby没有嵌套方法。好吧,我没有迷上这个名字。但是你怎么称呼它?是否有更好的方法来实现相同的功能?
答案 0 :(得分:2)
当人们谈论嵌套方法/函数时,它们通常意味着只在封闭方法中可见/可用的东西。对于您的示例而言,这不是真的 - 一旦定义,任何人都可以在该对象上调用它。
你所展示的是Ruby的单例方法:在一个类的一个实例上定义方法的能力(例如,当人们在ruby中说类方法时,那些实际上就是该实例上的单例方法Class
类)
至于是否有更好的方法,这是无法回答的,因为你还没有说出你想要解决的问题是什么。
答案 1 :(得分:1)
在方法中调用def
通常是错误的方法。你想要的是定义一个封装了这个和可能的其他方法的模块,然后根据需要将它混合在任何对象上:
module DateExtensions
def is_friday?
wday == 5
end
end
值得注意的是,strftime
可能会返回“星期五”以外的值,因为本地化可能会生效。您可以根据自己的位置获得“Freitag”或“Vendredi”。 wday
方法返回可预测的数值。
现在你可以把它混合在一起:
class Test
def today
date = Date.today
date.extend(DateExtensions)
date
end
end
通过在模块中声明这些方法,它们更明显地是一个包的一部分。这也意味着您不需要为您创建的Date的每个实例定义一个全新的方法。
更实用的Ruby方法是定义自己的Date子类,增加这种额外的行为。
答案 2 :(得分:0)
方法定义就像任何其他代码一样是代码。它们可以像任何其他代码一样出现在方法中。就像任何其他代码一样,每次运行该方法时都会执行它们。
所以,这个
class Foo
def foo
def bar
end
end
end
不是嵌套方法,而只是定义方法的方法。通过简单地调用它两次,注意生成的警告并检查周围模块的已定义方法,很容易看出这不是嵌套方法:
foo = Foo.new
Foo.public_instance_methods(false)
#=> [:foo]
foo.foo
Foo.public_instance_methods(false)
#=> [:foo, :bar]
foo.foo
# (irb):3: warning: method redefined; discarding old bar
# (irb):3: warning: previous definition of bar was here
正如您所看到的,bar
不嵌套在foo
内,而是在<{em>} foo
中定义 { {1}}。它仅在Foo
运行后定义,并且每次foo
运行时都会重新定义。
当然,您的示例有点不同,因为它不会在同一个类中覆盖该方法,而是在每次调用时将其定义在不同的类中。
请注意,有计划禁止此类用法,请参阅Feature #11665: Support nested functions for better code organization。
但是你怎么称呼它?
这是一种定义方法的方法。
是否有更好的方法来实现相同的功能?
很难说出你想要达到的目的是什么。
您可以使用您的方法创建foo
,并使用module
创建所有对象。那将是最接近的模拟。
其他解决方案需要对代码进行更大规模的重组,例如使用Decorator Design Pattern或在您的特定Rails用例中使用Presenter。