帮助ruby noob了解类继承

时间:2011-01-27 19:38:00

标签: ruby inheritance

我正在尝试通过构建一个基本的Campfire机器人来学习ruby,以便在工作中使用。我已经相当远了(它有效!)并且学到了很多东西(它有效!)但是现在我试图通过将要执行的动作分离到它们自己的类中来使它更复杂一些,这样它们就可以了在破碎时可以更容易地编写/修复。如果你有兴趣看到所有(可能是糟糕的)代码,那就是up on GitHub。但是为了这个问题,我会缩小范围。

理想情况下,我希望能够轻松地创建插件,将它们命名为类名,然后将它们放入项目根目录中的“actions”目录中,在运行时将它们实例化。我希望插件本身尽可能简单地编写,所以我希望它们都能从action类继承一些基本的方法和属性。

目前存在action.rb

module CampfireBot
  class Action
    @handlers = {}

    def initialize(room)
      @room = room
    end


    class << self
      attr_reader :handlers
      attr_reader :room

      def hear(pattern, &action)
        Action.handlers[pattern] = action
      end
    end
  end
end

@room是房间对象,@handlers是模式和块的哈希。我有点不明白为什么我必须进行class << self调用,但这是我可以让子插件类看到hear方法的唯一方法。

然后我尝试创建一个像这样的简单插件(名为Foo.rb):

class Foo < CampfireBot::Action

    hear /foo/i do
        @room.speak "bar"
    end
end
然后我将我的插件在bot.rb中实例化,如下所示:

def load_handlers(room)
  actions = Dir.entries("#{BOT_ROOT}/actions").delete_if {|action| /^\./.match(action)}
  action_classes = []
  # load the source
  actions.each do |action|
    load "#{BOT_ROOT}/actions/#{action}"
    action_classes.push(action.chomp(".rb"))
  end

  # and instantiate
  action_classes.each do |action_class|
    Kernel.const_get(action_class).new(room)
  end

  @handlers =  Action.handlers

end

当模式与以下匹配时,在room.rb内调用块:

handlers.each do |pattern, action|
  if pattern.match(msg)
    action.call($~)
  end
end

如果我在puts @room的初始化中Action,我会在控制台中看到房间对象打印出来。如果我在puts "foo"的{​​{1}}方法中Foo.rb,我会在控制台上打印出hear(因此,模式匹配正在运行)。但是,我无法从父类中读取foo对象(它作为一个nil对象出现)。很显然,我错过了一些关于它应该如何工作的东西。

此外,如果我做了一些事情来使插件更清晰(对于更大的功能)并重写它:

@room

我得到class Foo < CampfireBot::Action hear /foo/i do say_bar end def say_bar @room.speak "bar" end end

1 个答案:

答案 0 :(得分:1)

hear的定义可以从class << self块中取出并更改为:

 def self.hear(pattern, &action)
   Action.handlers[pattern] = action
 end

得到完全相同的结果。这也立即解释了这个问题。 hear是一种类方法。 say_bar是一种实例方法。您无法从类方法中调用实例方法,因为根本没有可用的类实例。

要了解class << self位,您必须自己进行阅读和实验:我不会尝试改进已经说过的内容。我只会说在class << self .. end块中,self指的是CampfireBot::Action类的本征类元类。这是包含CampfireBot :: Action类定义的Class类的实例。