Могу ли я включить метод модуля в класс? - PullRequest
0 голосов
/ 13 февраля 2019

Это мой код:

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 голосов
/ 13 февраля 2019

То, что вы, похоже, хотите сделать, это включить новые методы экземпляра, расширяя ваш класс новыми методами класса.Следующее основано на книге 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"
0 голосов
/ 13 февраля 2019

Хотя это вряд ли можно увидеть на практике, вы могли бы сделать это следующим образом.

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"

Почему?Поскольку x совпадает с self.x (self #=> main) и

self.is_a? Object
  #=> true

Примечание

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

является сокращением для

module X
  class << self
    def m
      #...
    end
  end
end
0 голосов
/ 13 февраля 2019

Если вы определяете 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 без аргументов опускаются в скобках.Вы также должны разделить определение метода и тело новой строкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...