Ruby:在使用模块

时间:2016-10-08 15:41:02

标签: ruby

我希望在使用Object#extend扩展实例时执行一些代码。在实例化一个类但是为一个模块时有点像initialize

这是扩展的documentation example

module Mod
  def hello
    "Hello from Mod.\n"
  end
end

class GoodKlass
  def hello
    "Hello from GoodKlass.\n"
  end
end

class BadKlass
  # something totally different
end

good = GoodKlass.new
good.hello         #=> "Hello from GoodKlass.\n"
good.extend(Mod)   #=> #<GoodKlass:0x401b3bc8>
good.hello         #=> "Hello from Mod.\n"

例如,如果Mod用于extend而不是GoodKlass的实例,我希望显示警告或加注:

bad = BadKlass.new
bad.extend(Mod)   #=> raise "Mod cannot extend BadKlass"

2 个答案:

答案 0 :(得分:3)

您可以在模块中定义self.extended

module Mod
  def self.extended(base)
    raise "Cannot extend #{base}" unless base.is_a?(GoodKlass)
  end

  def hello
    "Hello from Mod.\n"
  end
end

答案 1 :(得分:1)

你对这个问题的评论,回复我的评论,证实了我的怀疑。你所做的不是扩展类,而是扩展类的特定实例。让我们看看你的代码做了什么。

good = GoodKlass.new
good.hello       #=> "Hello from GoodKlass.\n"
GoodKlass.hello  #=> NoMethodError: undefined method `hello' for GoodKlass:Class
good.extend(Mod)
GoodKlass.hello  #=> NoMethodError: undefined method `hello' for GoodKlass:Class
good.hello       #=> "Hello from Mod.\n"
very_good = GoodKlass.new
very_good.hello  #=> "Hello from GoodKlass.\n"

如您所见,hello仅在实例good上定义。

请注意

GoodKlass.methods.include?(:hello)          #=> false
good.methods.include?(:hello)               #=> true 

如果那不是你想要的,有两种可能性。我参考了

class VeryGoodKlass
end

讨论两者。

1。 Extend班级

在您的应用程序中(对该问题的ref评论),这种方法可以让您创建一个可以调用File::jpg?的类方法File.jpeg?("cat.jpg")

要将Mod的实例方法hello转换为GoodKlass的类方法,您需要使用Object#extend扩展类(不是类的实例) 。要防止其他类扩展模块,请使用模块中的回调方法Module#extended

module Mod
  def self.extended(base)
    raise ArgumentError, "Cannot extend #{base}" unless base == GoodKlass
  end
  def hello
    "Hello from Mod"
  end
end

class GoodKlass
  def self.hello
    "Hello from GoodKlass"
  end
end

GoodKlass.hello           #=> "Hello from GoodKlass"
GoodKlass.extend(Mod)
GoodKlass.hello           #=> "Hello from Mod"
VeryGoodKlass.extend(Mod) #=> ArgumentError: Cannot extend VeryGoodKlass

2。在课程中包含该模块

要将Mod的实例方法添加到GoodKlass(保留它们的实例方法),您需要使用Module#include包含该模块。要防止其他类包含模块,请在模块中使用回调方法#included

在你的应用程序中,这将允许你编写一个实例方法File#jpg? 1 ,如下所示:

f = File.new('cat.jpg')
f.jpg?

你可以这样做。

module Mod
  def self.included(base)
    raise ArgumentError, "Cannot include #{base}" unless base == GoodKlass
  end
  def hello
    "Hello"
  end
end

class GoodKlass
end

good = GoodKlass.new
GoodKlass.include(Mod)
GoodKlass.hello            #=> NoMethodError: undefined method `hello' for GoodKlass:Class
good.hello                 #=> "Hello" 
VeryGoodKlass.include(Mod) #=> ArgumentError: Cannot include VeryGoodKlass

1。也许是File.basename(f.path).end_with?(".jpg")