NoMethodError:未定义的方法`喵?'为# - ruby mixin失败了吗?

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

我正在玩一些ruby mixins的基础知识,并且由于某种原因无法访问我的模块中的行为。

在Ruby Fiddle上运行它:

module Cats
  MEOW = "meow meow meow"

  def Cats.meow?
    return Cats::MEOW
  end
end

class Example
  include Cats

  def sample
    return "it's a sample"
  end
end

e = Example.new
puts e.sample
puts e.meow?

这使得NoMethodError: undefined method 'meow?' for #不断回归

我对如何使用tutorialspoint的mixins的理解让我觉得我应该能够有效地调用e.meow?,并获得与调用Cats.meow?相同的结果。

这是RubyFiddle中的代码。

令人难以置信的基本,但任何想法,我在这里跌倒?

ruby module mixins
2个回答
1
投票

事实证明,在定义Cats.meow?时我过于具体。如果要将模块用作mixin,则需要更一般地定义方法,而不是针对其特定的模块命名空间。

而不是

def Cats.meow?
  ...
end

应该是的

def meow?
  ...
end 

这使您可以调用e.meow?,因为方法定义不再仅限于Cats命名空间。

哎呦。


1
投票

作为在Ruby中使用includeextend的一般规则:

如果要将模块用作命名空间

module Outer
  module Inner
    def self.my_method
      "namespaced method!"
    end
  end
end

你使用它像Outer::Inner::my_methodOuter::Inner.my_method

如果你想将模块用作mixin:

# In some cases it makes sense to use names ending in -able, since it expreses
# what kind of messages you can send to an instance or class that mixes
# this module in.
# Like Devise's Recoverable module: https://github.com/plataformatec/devise/blob/f39c6fd92774cb66f96f546d8d5e8281542b4e78/lib/devise/models/recoverable.rb#L24

module Fooable
  def foo
    "#{self} has been foo'ed!"
  end
end

然后你可以include它(Something的实例获得#foo):

class Something
  include Fooable # Now Something.new can receive the #foo message.
end

Something.new.foo
=> "#<Something:0x0055c2dc104650> has been foo'ed!"

或者你可以扩展它(Something本身将#foo作为类消息获得):

class Something
  extend Fooable # Now Something can receive the #foo message.
end

Something.foo
=> "Something has been foo'ed!"
© www.soinside.com 2019 - 2024. All rights reserved.