Мета-программирование - динамический метод - PullRequest
0 голосов
/ 27 декабря 2018

У меня есть 2 версии класса Computer здесь.Я вижу, что Computer2 намного лучше, чем Computer1.Оба компьютерных класса дают одинаковый результат.Как класс Computer2 отличается от класса Computer1?

class DataSource
  def cpu_info(computer_id)
    "#{computer_id}'s CPU"
  end

  def cpu_price(computer_id)
    12
  end

  def mouse_info(computer_id)
    "#{computer_id}'s mouse"
  end

  def mouse_price(computer_id)
    27
  end

  def monitor_info(computer_id)
    "#{computer_id}'s monitor"
  end

  def monitor_price(computer_id)
    33
  end
end

# Step 1
class Computer1
  def initialize(computer_id, data_source)
    @id = computer_id
    @ds = data_source
  end

  def cpu
    get_info :cpu
  end

  def mouse
    get_info :mouse
  end

  def monitor
    get_info :monitor
  end

  def get_info(component)
    component_info = @ds.send("#{component}_info", @id)
    component_price = @ds.send("#{component}_price", @id)
    data = "The work station #{component_info} is about #{component_price}$"
    return data;
  end
end

computer = Computer1.new(1, DataSource.new)
computer.cpu #The work station 1's CPU is about 12$

# Step 2 - Further simplified
class Computer2
  def initialize(computer_id, data_source)
    @id = computer_id
    @ds = data_source
  end

  def self.get_info(component)
    define_method(component) do
      component_info = @ds.send("#{component}_info", @id)
      component_price = @ds.send("#{component}_price", @id)
      data = "The work station #{component_info} is about #{component_price}$"
      return data;
    end
  end

  get_info :mouse
  get_info :cpu
  get_info :monitor
end

computer = Computer2.new(1, DataSource.new)
computer.cpu #The work station 1's CPU is about 12$

Мой вопрос: как это возможно, поскольку в классе Computer2 нет экземпляра метода cpu

computer = Computer2.new(1, DataSource.new)
computer.cpu

Ответы [ 2 ]

0 голосов
/ 27 декабря 2018

В классе Computer2 вы вызываете метод: get_info:

get_info :mouse
get_info :cpu
get_info :monitor

Эти методы вызывают функцию ruby: define_method (https://apidock.com/ruby/Module/define_method), этот метод создает именованную функцию для вашего экземпляра вв этом случае и после вызова get_info(:cpu) у вас есть метод .cpu для вызова с блоком подачи:

component_info = @ds.send("#{component}_info", @id)
component_price = @ds.send("#{component}_price", @id)
data = "The work station #{component_info} is about #{component_price}$"
return data;
0 голосов
/ 27 декабря 2018

Когда ваш класс Computer2 загружен, self вызывает get_info метод класса с аргументом :cpu, который позже используется для определения метода экземпляра cpu для вашего экземпляра Computer2.

Read define_method

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