繁体   English   中英

Ruby:在使用模块扩展实例时做一些事情

[英]Ruby: Do something when extending an instance with a module

当使用Object#extend 扩展实例时,我想执行一些代码。 有点像实例化类时的initialize ,但用于模块。

这是扩展文档示例

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"

您可以在模块中定义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

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

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

在您的应用程序中(对问题的引用评论),这种方法将允许您创建一个类方法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")

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM