1

I was reading Why's (Poignant) guide to Ruby, and came across a method that didn't quite work out as expected. The method is aimed to return a value (from a hash) for a given string, somewhat like an encoder-decoder. Originally, the method was written inside a class String, but I modified it to change the classname. Here's the code:

class NameReplacer
  @@syllables = [

      {"Paij" => "Personal","Gonk" => "Business", "Blon" => "Slave", "Stro" => "Master", "Wert" => "Father", "Onnn" => "Mother"},
      {"ree" => "AM", "plo" => "PM"}
  ]

  # method to determine what a certain name of his means
  def name_significance
    # split string by -
    parts = self.split("-")
    # make duplicate of syllables
    syllables = @@syllables.dup
    signif = parts.collect {|name| syllables.shift[name]}
    #join array returned by " " forming a string
    signif.join(" ")
  end
end

To run this code, the book simply uses "Paij-ree".name_significance. But when I tried doing the same thing, I got a NoMethodError - in <top (required)>: undefined method NameReplacer for "Paij-ree":String (NoMethodError).

I got the same error when I tried: print "Paij-ree".NameReplacer.new.name_significance

I assume this worked in the book because the method was written in a class String, which, I guess, would be equal to having this method in Ruby's String class. Due to that, something like "paij-ree".name_significance" would not throw an error, because the "paij-ree" would be a String object, and String class does have the method name_significance.

However, how do I accomplish this with my current code? Apologies if this question seems stupid.

4

2 回答 2

2

结果相同的三种方法:

# monkey-patching a class
class String
  def appendFoo
    self + "foo"
  end
end

"a".appendFoo
# => "afoo"

# using an external class method
class FooAppender
  def self.appendFoo(string)
    string + "foo"
  end
end

FooAppender.appendFoo("a")
# => "afoo"

# using an external instance method
class StuffAppender
  def initialize(what)
    @what = what
  end

  def append_to(string)
    string + @what
  end
end

new StuffAppender("foo").append_to("a")
# => "afoo"

self表示定义该方法的对象。您不能selfNameReplacer类中使用来引用字符串,它将是NameReplacer实例(在像您这样的实例方法中)。

于 2015-10-13T02:07:22.027 回答
1

正如其他人所提到的,该代码取决于 String 类。您的另一种选择是使用您的类扩展 String 类,如下所示:

class NameReplacer < String    
  @@syllables = [
    {
      "Paij" => "Personal",
      "Gonk" => "Business",
      "Blon" => "Slave",
      "Stro" => "Master",
      "Wert" => "Father",
      "Onnn" => "Mother"
    },
    {
      "ree" => "AM",
      "plo" => "PM"
    }
  ]

  # method to determine what a certain name of his means
  def name_significance
    # split string by -
    parts = self.split("-")
    # make duplicate of syllables
    syllables = @@syllables.dup
    signif = parts.collect {|name| syllables.shift[name]}
    #join array returned by " " forming a string
    signif.join(" ")
  end
end

然后像这样使用它:

p = NameReplacer.new("Paij-ree")
puts p.name_significance
于 2015-10-13T02:11:18.797 回答