在ruby中将方法添加到内置类的正确方法是什么?

问题描述 投票:2回答:3

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

有人提到这不是向内置类添加功能的最佳方法。 我的问题是,正确的方法是什么?

ruby string built-in-types
3个回答
2
投票

tenebrousedge可能暗示refinements

或者说,而不是修补String。通常情况下,monkeypatching会产生比它解决的问题更多的问题。如果String已经知道alpha?并且它做了不同的事情怎么办?

例如,未来版本的ruby可能会添加String#alpha?,它将正确处理unicode

'新幹線'.alpha? # => true

和你的代码一样,会用劣质版本覆盖这个内置功能。现在你的应用程序在各种各样的地方出现问题,因为stdlib / rails采用了新的行为。混沌!

这就是说:尽可能避免monkeypatching。当你无法避免时,使用改进。


1
投票

只想添加@ 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?

0
投票

在扩展核心类时,我想在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

我希望这个对你有用

© www.soinside.com 2019 - 2024. All rights reserved.