2014-04-07 3 views
0

При наследовании класса, я хочу, чтобы сохранить класс переменные в наследуя класс вместо родительского класса ... вот так ...переменных Присвоить класс для унаследованных классов

class Foo 
    def self.inherited klass 
    klass.title = klass.to_s 
    end 

    def self.title= title 
    @@title = title 
    end 

    def self.title 
    @@title 
    end 
end 

class Bar < Foo 
end 

class Baz < Foo 
end 

Bar.title # returns `Baz` instead of `Bar` 
Baz.title 

Это надуманное например, потому что после игры с ним я больше хочу просто понять, чем что-либо.

ответ

1

Вам нужно изменить переменную класса на переменную экземпляра.

class Foo 
    def self.inherited klass 
    klass.title = klass.to_s 
    end 

    def self.title= title 
    @title = title 
    end 

    def self.title 
    @title 
    end 
end 

class Bar < Foo 
end 

class Baz < Foo 
end 

Bar.title # => "Bar" 
Baz.title # => "Baz" 

@@title переменная класса является общей переменной. Baz, Bar и Foo все используют одну и ту же переменную класса @@title. Когда вы сделали class Baz < Foo ;end, тогда @@title был обновлен на имя Baz, таким образом, все вызовы метода getter #title дает обновленное значение переменной @title.

Следуйте код ниже: -

class Foo 
    def self.inherited klass 
    klass.title = klass.to_s 
    end 

    def self.title= title 
    @@title = title 
    end 

    def self.title 
    @@title 
    end 
end 

class Bar < Foo 
end 

# see the output here 
Bar.title # => "Bar" 

class Baz < Foo 
end 

# here the output changed, as @@title value is holding the currently updated 
#value 
Bar.title # => "Baz" 
Baz.title # => "Baz" 
+0

так, что я пытаюсь понять, почему все 3 класса совместно используют ту же переменную класса. я изначально использовал переменную экземпляра, но он казался контр-интуитивным, поскольку подразумевал, что эти переменные будут доступны для экземпляров классов .... но поскольку это метод класса, переменная экземпляра ссылается на класс (экземпляр класс 'Class'? – brewster

+0

@brewster Вот как он разработан .. * переменные класса * будут разделены. Почему дизайн, я не знаю. Но я могу заверить, как это происходит. :-) –

+0

Я имею в виду, так как объявлено технически 3 класса, я пытался понять, почему я не мог объявить 3 независимых переменных класса между ними. – brewster

0

Вы можете сделать это с помощью Module#class_variable_get и Module#class_variable_set:

class Foo 
    def self.title= title 
    class_variable_set(:@@title, title) 
    end 
    def self.title 
    class_variable_get(:@@title) 
    end 
end 

class Bar < Foo 
end 

class Baz < Foo 
end 

Bar.title = 'Bar' 
Baz.title = 'Baz' 

Bar.title   #=> "Bar" 
Bar.title = "Cat" 

Baz.title   #=> "Baz" 

Bar.class_variables #=> [:@@title] 
Baz.class_variables #=> [:@@title] 
Foo.class_variables #=> [] 

Foo.methods(false) #=> [:title=, :title] 
Bar.methods(false) #=> [] 
Baz.methods(false) #=> [] 

Если мы должны были выполнить Bar «са поглотитель перед его сеттера, мы получим :

Bar.title #=> NameError: uninitialized class variable @@title in Bar 

При желании переменные класса c отформатированы (в nil, скажем), добавив следующее определение класса:

def self.inherited klass 
    klass.class_variable_set(:@@title, nil) 
end 
Смежные вопросы