А все дело в чем? В Руби каждый класс - это тоже объект, а переменные типа @@variable, которые я раньше считал "переменными класса", на самом деле принадлежат иерархии наследования (как-то так).
То есть, сочинив классу потомка, мы будем иметь доступ не к новой @@variable, а все к той же самой, и, поменяв ее в потомке, мы изменим ее и в предке! Не совсем то, что надо, если речь идет о переменной класса (ЕМНИП, в C++ оно называлось static).
Дальше начинается магия. В Руби _все_ является объектом, в том числе, как уже было сказано, и сам класс. А значит, мы можем использовать @variable в определении класса, и эта самая @variable будет принадлежать не иерархии наследования, а только самому нашему классу.
Но как организовать к этой переменной доступ? Об этом - после рекламы далее.
Для этого мы будем использовать Eigenclass (собственный класс). До конца я в этом еще не разобрался, но по сути, у каждого класса Руби есть этакий надкласс (Singleton class, Eigenclass, как угодно), объектом которого и является этот самый каждый класс. То есть переменные класса (те, что @variable, но не переменные экземпляра) - всего лишь instance variables of Eigenclass.
Получаем такую запись:
class A
@x = 1 #вот наша переменная, которая не должна
#отойти к наследникам
class << self #а вот тут происходит магия - мы
#обращаемся к Eigenclass!
attr_accessor :x #для которого x - не более чем
#instance variable, к которой он
#может обращаться, как и к любой i_v
end
end
#Теперь вполне можно использовать
A.x # => 1
class B < A
@x = 5
end
A.x # => 1
B.x # => 5
То есть, когда мы унаследуем от класса А, мы получаем другую переменную @x (используя @@x и не используя эти телодвижения, мы бы получили переменную уровня иерархии наследования, которая поменялась бы в предке, если бы мы поменяли ее в наследнике).
Как-то так.
Update: Проверил в irb - вроде как можно выкрутиться еще проще, без явного привлечения магии Eigenclass:
class A
@x = 1
def self.x
@x
end
end
Не получится "красиво сделать аксессор", но зато работать все должно так же. И наследники подгадить не смогут.
Комментариев нет:
Отправить комментарий