Более подробно о методе inherited

2 comments

in Разработка

Многие из вас слышали о замечательном методе inherited.

Если кто-то не понимает о чем сейчас идёт речь, то поясню, что этот метод вызывается, когда какой-нибудь класс унаследовал другой (базовый) класс. Сегодня вы узнаете, как этот метод может быть полез в хозяйстве ;)

Например:

class A
  def self.inherited(child)
    puts “Now I am parent of class #{child}!”
  end
end
 
class B < A
end
 
#=> “Now I am parent of class B”

Такие методы называются методами обратного вызова (callback).

Но для чего оно может пригодиться нам?

Например, вы разрабатываете свой фреймворк и вам необходимо узнать о классах, которые унаследовали базовый класс:

class MyController < MyFrameWork::Base

На этой недели я разрабатывал свою систему виджетов, и воспользовался этой техникой:

class MyCustomWidget < Widgets::Base

Скрипт читал каждый .rb файл в директории “widgets” и загружал его в память. Как только интерпретатор замечал, что какой-нибудь класс унаследовал Widgets::Base, он сразу заносил имя этого класса в хранилище.

Проблема в том, что при срабатывании метода inherited вам недоступны методы, объявленные в теле класса – потомка. Потому что интерпретатор еще не успел занести методы класса в память. Это может стать проблемой. Я обошел эту проблему простым путём: узнал о всех классах, унаследовавших базовый класс, позволил интерпретатору загрузить методы классов, а уже после этого создал объекты классов:

def initialize
  self.pool = EasyWidgets::Pool.new
  self.load_widgets
  self.pool.init_objects_pool
end

Более подробно об объектном пуле

Хорошо это или плохо?

С одной стороны вам не нужно создавать и следовать naming-convention. Как, например в Rails:

[main_controller.rb]: MainController < базовый_класс

Вы сможете делать что-то вроде этого:

[любое_имя_файла.rb]: MySuperClass < базовый_класс

Меня огорчил тот факт, что метод inherited срабатывает ДО того, как руби занёс методы класса в память.

Но по сути это не является серьезной проблемой.

Я думаю это первое «ограничение», которое мне удалось встретить при работе с ruby :)

{ 2 comments… read them below or add one }

1 Vladimir Июль 15, 2010 в 23:10

Скорей всего, это ограничение сделано специально с целью предотвращения утечки памяти или еще по какому-то мотиву, при этом разработчики Ruby позаботились о несложных обходных маневрах. Это повсеместная практика разработки на Ruby: зделать несколько сложнее написание потенциально опасного кода. Например, Ruby защищает методы и атрибуты private классов, однако, фактически можно получить доступ к чему угодно используя instance_eval() и send().

Ответить

2 Роман Июль 28, 2010 в 22:46

«Более подробно об объектном пуле»
ссылка не работает

«self.pool = EasyWidgets::Pool.new»
а почему не @pool = EasyWidgets::Pool.new
pool это же instance variable

Ответить

Leave a Comment

Previous post:

Next post: