LINUX.ORG.RU

Разширение инстансов класа разными модулями

 , ,


0

1

Задача: у меня есть некоторое количество «задач», которые можно выполнять параллельно. Описание задачи являет собой модуль с методами и константами. Есть клас-враппер, который собственно и запускает задачи.

Проблемма: я не нашел (хорошего) способа как «inject`ить» все внутренности модуля в свой отдельно взятый инстанс враппера.

Я перепробывал

  • class_eval(«include ..»)
  • instance_eval(«include ..»)
  • Object.extend()

Но ни один не помог. Наиболее близко ктому что мне надо был extend. Но он к сожалению не «копировал» константы. А документация по этому поводу разходится

extend(module, ...) → obj click to toggle source Adds to obj the instance methods from each module given as a parameter.

extend_object(obj) → obj click to toggle source Extends the specified object by adding this module’s constants and methods (which are added as singleton methods). This is the callback method used by Object#extend.

Сейчас я вижу 2 возможных костыляworkaround`а:

  • возвращать каждую константу в отдельном методе
  • в инстансе работать на прямую с методами/константами

Код прототипа (я надеюсь гуру понимают почему он работает правильно)

#!/usr/bin/env ruby
# encoding: UTF-8

require 'thread'
require_relative 'module_a'
require_relative 'module_b'

class TaskRunner
    def initialize(_module)
        print "#{self.__id__}:#{_module.name.to_s}\n"
        self.class.class_eval("include #{_module}")
        process_test_method
    end

    def process_test_method
        print "#{self.__id__}:#{test_method}\n"
    end
end

scheduled_tasks = []

Module.constants.select { |module_name|
    module_name.to_s.start_with?('Module_')
}.each { |name|
    scheduled_tasks << Thread.new do
        TaskRunner.new(Kernel.const_get(name))
    end
}

scheduled_tasks.each { |task| task.join }

модуль №1

#!/usr/bin/env ruby
# encoding: UTF-8
#
module Module_a
    PROVIDES = 'architectures'
    def test_method
        'I am from Module_a::method'
    end
end

модуль №1

#!/usr/bin/env ruby
# encoding: UTF-8
#
module Module_b
    PROVIDES = 'platforms'
    def test_method
        'I am from Module_b::method'
    end
end

★★★★★

Ты же здесь инклудишь модуль в класс каждый раз как создается объект, у тебя постоянно методы переопределяются во всех объектах. Константы определяются в классе/модуле, в объекте доступны self.class::SOME_CONST . Откуда такой изврат а?

special-k ★★★★
()

Тебе надо элементарно наследовать

class A < TaskRunner
    PROVIDES = 'architectures'
    def test_method
        'I am from Module_a::method'
    end
end

special-k ★★★★
()
Ответ на: комментарий от special-k

в таком случае констаты не будут видны из методов которые обьявлены в TaskRunner`e

/home/vv/work/own/ruby/portage3/task2/scheduler.rb:11:in `initialize': uninitialized constant TaskRunner::PROVIDES (NameError) from runner.rb:13:in `new'

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от special-k

теперь понял.

вся фишка в

self.class::PROVIDES

спасибо

ZuBB ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.