2015-03-10 7 views
0

Я пытаюсь сделать то, что я описал в названии, потому что я хочу использовать значение переменной класса подкласса в родительском. На самом деле, я нашел способ сделать это, но я чувствую, что могу сделать что-то приятнее. Вот мой текущий код:Ruby: разделите переменную класса между родительским классом и его подклассами

class Parent 
    def self.test_settings 
    const_set "PATH", "/tmp/#{self.name}" 
    end 
end 

class Sub1 < Parent 
    def self.name 
    "one" 
    end 
    test_settings if Rails.env.test? 
end 

class Sub2 < Parent 
    def self.name 
    "two" 
    end 
    test_settings if Rails.env.test? 
end 

Моя оригинальная версия - что не работает, является:

class Parent 
    def self.test_settings 
    const_set "PATH", "/tmp/#{@@name}" 
    end 
    test_settings if Rails.env.test? 
end 

class Sub1 < Parent 
    @@name = "sub1" 
end 

class Sub2 < Parent 
    @@name = "sub2" 
end 

поясню: я использовал метод класса вместо переменной (@ @name), который я пробовал до безуспешно. Кроме того, мне пришлось переместить вызов функции test_settings if Rails.env.test? в подклассы, потому что он рассмотрит self как родительский класс, если я поместил там этот код.

Я бы по достоинству оценил любые предложения по его улучшению и почему моя оригинальная идея (используя имя @@ и вызов метода test_settings в родительском классе) не работает.

+0

у вас есть те же опечатки ('Paernt' вместо' Parent', 'Rail' вместо' Rails ') в вашем коде? –

+0

'@@ name' называется переменной * класса *, которая даст вам самое последнее значение и является переменной _shared_ через наследование. Другой вопрос я не пожалел. :) –

+0

Обратите внимание, что реализация 'self.name' overwrites/shadows [' Module # name'] (http://ruby-doc.org/core-2.2.1/Module.html#method-i-name) – Stefan

ответ

0

Для того, чтобы получить его работу, вы должны определить @@name в Parent классе:

class Parent 
    @@name = nil 

    def self.test_settings 
    const_set "PATH", "/tmp/#{@@name}" 
    end 
end 

class Sub1 < Parent 
    @@name = 'sub1' 
    test_settings 
end 

class Sub2 < Parent 
    @@name = 'sub2' 
    test_settings 
end 

puts Sub1::PATH #=> /tmp/sub1 
puts Sub2::PATH #=> /tmp/sub2 

В противном случае Рубин покажет вам, что @@name не инициализирован.

+1

Смотреть с этим именем - @@ name будет иметь значение «sub2» в обоих подклассах после выполнения этого фрагмента –

0

Это позволяет избежать использования переменных класса, но ИМХО понятнее, и позволяет избежать потенциальных проблем намекал на here

class Parent 
    def self.test_settings(name) 
    const_set "PATH", "/tmp/#{name}" 
    end 
end 

class Sub1 < Parent 
    test_settings("sub1") if Rails.env.test? 
end 

class Sub2 < Parent 
    test_settings("sub2") if Rails.env.test? 
end 



irb(main):042:0> Sub1::PATH 
=> "/tmp/sub1" 
irb(main):043:0> Sub2::PATH 
=> "/tmp/sub2"