Передача класса в качестве аргумента в Ruby - PullRequest
0 голосов
/ 25 марта 2020

У меня есть класс Ruby со всеми методами stati c. Я хочу использовать эти методы в другом классе. Передача только имени класса работает, но интересно, правильный ли это путь к go или есть другой способ.

class Foo
    IDENTIFIER = 'UYT78'
    def self.some_data
      DB.fetch_records
    end

    # and so forth
end

class Bar
    IDENTIFIER = 'XXXXX'
    def self.some_data
      DB.fetch_records
    end

    # and so forth
end

class Reporter

  def report
    Foo.some_data.select {|x| x.id == Foo::identifier}
  end

  def other_report
    Bar.some_data.select {|x| x.id == Foo::identifier}
  end
end

Может ли Reporter быть изменен, чтобы принимать Foo в качестве аргумента методов, чтобы эти методы можно было повторно -используется на основании передаваемого аргумента?

Reporter.report(Foo)
Reporter.report(Bar)

и метод отчета выглядит как

def report(klass)
  klass.some_data.select {|x| x.id == Foo::identifier}
end

Этот подход работает, но передача имени класса в качестве аргумента выглядит неправильно? Или может быть это так?

Ответы [ 3 ]

1 голос
/ 25 марта 2020

То, что вы пытаетесь сделать, это хорошо, но вместо того, чтобы проходить такой урок, я бы использовал ruby s require.

foo.rb

class Foo
  IDENTIFIER = 'UYT78'.freeze

  def self.some_data
    'Foo'
  end
end

bar.rb

class Bar
  IDENTIFIER = 'XXXXX'.freeze

  def self.some_data
    'Bar'
  end
end

reporter.rb

require './foo'
require './bar'

class Reporter

  def report
    p Foo.some_data
    p Foo::IDENTIFIER
  end

  def other_report
    p Bar.some_data
    p Bar::IDENTIFIER
  end
end

Reporter.new.report
puts '----------------'
Reporter.new.other_report

Что бы вернуть, как показано ниже (Просто и пример) -

"Foo"
"UYT78"
----------------
"Bar"
"XXXXX"

На мой взгляд, это намного чище.

1 голос
/ 25 марта 2020

Это нормально ... как правило, это называется duck-typing ..., поскольку переданный класс поддерживает метод #some_data, на самом деле не имеет значения, какой именно класс c это. Если это похоже на утку и крякает как утка ...

Возможно, вы захотите сохранить целевой класс при инициализации.

class Reporter
  attr_accessor :klass
  def initialize(klass)
    self.klass = klass
  end

  def report
    klass.some_data.select
  end
end

my_foo_reporter = Reporter.new(Foo)

my_foo_reporter.report # calls some_date on Foo class
0 голосов
/ 25 марта 2020

Возможно, это то, что вы ищете.

class Foo
  IDENTIFIER = 'UYT78'
  def self.some_data
    ['ABC21', 'UYT78']
  end
end

class Bar
  IDENTIFIER = 'XXXXX'
  def self.some_data
    ['XXXXX', 'DEF38']
  end
end

class Reporter
  def report(klass)
    k = Module.const_get(klass)
    k.public_send(:some_data).select {|x| x == k::IDENTIFIER}
  end
end

reporter = Reporter.new

reporter.report("Foo") #=> ["UYT78"] 
reporter.report("Bar") #=> ["XXXXX"] 
reporter.report(:Bar)  #=> ["XXXXX"] 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...