我可以在类中包含模块方法吗?

时间:2019-02-13 19:21:16

标签: ruby

这是我的代码:

module X
  class << self
    def x() %s(hi5) end
  end

  def y() rand(65..122).chr end
end

class Object
  include X

  # Here I want class Object to have x() from the X module.
end

puts y # => A random character from ('A'..'z')
# puts x

我想以与致电x相同的方式致电y。我可以这样做吗?

3 个答案:

答案 0 :(得分:2)

如果您以与定义x相同的方式定义y,则可以。 class << self部分仅使x成为模块方法,不能与include一起添加。因此要解决:

module X
  def x
    %s(hi5)
  end

  def y
    rand(65..122).chr
  end

  def self.z
    :nope
  end
end

class Object
  include X
end

puts x
puts y
puts z # Error, as this can't be included

此处使用z声明方法添加了self.z,它比class << self少了很多麻烦,但效果相同。

请注意,不带参数的Ruby方法的括号被省略。您还应该用换行符分隔方法定义和主体。

答案 1 :(得分:2)

您似乎想要做的是包括新的实例方法,同时用新的类方法扩展您的类。以下是基于PICK AX的书:

module X
  module ClassMethods
    def x()
      puts "In class"
    end
  end

  def y()
    puts "In instance"
  end

  def self.included(host_class)
    host_class.extend(ClassMethods)
  end
end

class Object
  include X
end

现在

# Test the instance method
Object.new.y  # Prints "In instance"

# Test the class method
Object.x   # Prints "In class"

答案 2 :(得分:1)

尽管在实践中不太可能看到这种情况,但您可以按照以下步骤进行操作。

module X
  def self.x
    :hi5
  end

  def self.v(str)
    str.capitalize
  end

  def self.z(str)
    yield(str)
  end

  def y
    :ho
  end
end

X.x
  #=> :hi5
X.v("cat")
  #=> "Cat"
X.z("cat") { |s| s.upcase }
  #=> "CAT" 

class Object
  include X
  X.methods(false).each do |m|
    define_method(m) { |*args, &block|
      X.method(m).call(*args, &block) }
  end
end
  #=> [:v, :x, :z]

Object.instance_methods && [:x, :v, :z, :y]
  #=> [:x, :v, :z, :y]

o = Object.new

o.x
  #=> :hi5
o.v("cat")
  #=> "Cat"
o.z("cat") { |s| s.upcase }
  #=> "CAT"
o.y
  #=> :ho

这也可以。

x #=> :hi5
v("cat")
  #=> "Cat"
z("cat") { |s| s.upcase }
  #=> "CAT"
y #=> "m"

为什么?因为xself.xself #=> main)和

相同
self.is_a? Object
  #=> true

注意

module X
  def self.m
    #...
  end
end

的简写
module X
  class << self
    def m
      #...
    end
  end
end