在exercism.io,我已经在Pangram Problem
提交了Ruby
的解决方案。
为了解决这个问题,我为String
类创建了一个名为alpha?
的方法,它确定一个字符是否为alphabetial('a'..'z')。此方法位于一个模块中,然后我将其包含在String类中。
这是我的代码:
module Str_Plus
def alpha?
self[/[a-zA-Z]+/] == self
end
end
class Pangram
String.include Str_Plus
...
end
有人提到这不是向内置类添加功能的最佳方法。 我的问题是,正确的方法是什么?
tenebrousedge可能暗示refinements。
或者说,而不是修补String
。通常情况下,monkeypatching会产生比它解决的问题更多的问题。如果String已经知道alpha?
并且它做了不同的事情怎么办?
例如,未来版本的ruby可能会添加String#alpha?
,它将正确处理unicode
'新幹線'.alpha? # => true
和你的代码一样,会用劣质版本覆盖这个内置功能。现在你的应用程序在各种各样的地方出现问题,因为stdlib / rails采用了新的行为。混沌!
这就是说:尽可能避免monkeypatching。当你无法避免时,使用改进。
只想添加@ sergio的答案,并附上一个具体的做什么例子(写作获得代码格式的答案)。制作自己的课程/模块。像alpha?
这样的方法不必在String
本身上定义为有用且可重复使用,并且将其放在那里,即使进行了改进,也要求进行名称冲突。任何执行此操作的宝石都会立即出现在我的糟糕列表中,因为它只需要两个宝石来为他们想要添加的方法选择相同的名称并且它是混乱的。
相反,最好将方法包含在自己的类中。我会选择一个比MyStringIdentifier
更好的名字,但你没有必要
作为一个模块:
module MyStringIdentifier
# allows you to use `MyStringIdentifer.any_module_method_name_here`
extend self
def alpha?(string)
!!(/^[a-zA-Z]+$/ =~ string)
end
end
MyStringIdentifier.alpha?("hello")
或者,作为一个类:
class MyStringIdentifier
attr_reader :string
def initialize(string)
@string = string.to_s
end
def alpha?
!!(/^[a-zA-Z]+$/ =~ string)
end
end
MyStringIdentifier.new("hello").alpha?
在扩展核心类时,我想在core_ext
目录中添加一个lib
目录。
创建和initializer以加载自定义扩展(例如:config/initializers/core_exts.rb
)。并在其中添加以下行:
Dir[File.join(Rails.root, "lib", "core_ext", "*.rb")].each {|file| require file }
你的扩展名如下:
#lib/core_ext/string.rb
class String
def alpha?
self[/[a-zA-Z]+/] == self
end
end
现在从控制台你可以做到
"ABCD".alpha? # true
"ABC1".alpha? # false
"1234".alpha? # false
我希望这个对你有用