Попросите метод родительского класса получить доступ к константам подкласса
Например:
class Animal
def make_noise
print NOISE
end
end
class Dog < Animal
NOISE = "bark"
end
d = Dog.new
d.make_noise # I want this to print "bark"
Как это сделать? В настоящее время он говорит
uninitialized constant Animal::NOISE
Ответы
Ответ 1
Я думаю, что вы действительно не хотите постоянной; Я думаю, что вам нужна переменная экземпляра в классе:
class Animal
@noise = "whaargarble"
class << self
attr_accessor :noise
end
def make_noise
puts self.class.noise
end
end
class Dog < Animal
@noise = "bark"
end
a = Animal.new
d = Dog.new
a.make_noise #=> "whaargarble"
d.make_noise #=> "bark"
Dog.noise = "WOOF"
d.make_noise #=> "WOOF"
a.make_noise #=> "whaargarble"
Однако, если вы уверены, что хотите константу:
class Animal
def make_noise
puts self.class::NOISE
# or self.class.const_get(:NOISE)
end
end
Ответ 2
один способ сделать это без переменных экземпляра класса:
class Animal
def make_noise
print self.class::NOISE
end
end
class Dog < Animal
NOISE = "bark"
end
d = Dog.new
d.make_noise # prints bark
Ответ 3
Я думаю, что у вас здесь неправильная концепция. Классы в Ruby аналогичны классам Java, Smalltalk, С#,... и все являются шаблонами для их экземпляров. Таким образом, класс определяет структуру и поведение, если его экземпляры, а также части структуры и поведение экземпляров его подклассов , но не наоборот.
Таким образом, прямой доступ от суперкласса к константе в подклассе вообще невозможен, и это хорошо. См. Ниже, как исправить это. Для определенных классов верно следующее:
-
class Animal
определяет метод make_noise
.
- экземпляры
class Animal
могут вызывать метод make_noise
.
-
class Dog
определяет константу NOISE
с ее значением.
- экземпляры
Dog
, а сам класс Dog
может использовать константу NOISE
.
Что не возможно:
- Экземпляры
Animal
или самого класса Animal
имеют доступ к константам класса Dog
.
Вы можете исправить это следующим изменением:
class Animal
def make_noise
print Dog::NOISE
end
end
Но это плохой стиль, потому что теперь ваш суперкласс (который является абстракцией о Dog
и других животных) теперь знает то, что принадлежит Dog
.
Лучшим решением будет:
- Определить абстрактный метод в классе
Animal
, который определяет, что make_noise
должен быть определен. См. Ответ fooobar.com/questions/142657/....
- Определите в своих конкретных классах метод снова, но теперь со ссылкой на константу.
Ответ 4
Если вы делаете это для настройки ваших подклассов, чтобы базовый класс имел доступ к константам, вы можете создать DSL для них следующим образом:
module KlassConfig
def attr_config(attribute)
define_singleton_method(attribute) do |*args|
method_name = "config_#{attribute}"
define_singleton_method method_name do
args.first
end
define_method method_name do
args.first
end
end
end
end
class Animal
extend KlassConfig
attr_config :noise
def make_noise
puts config_noise
end
end
class Dog < Animal
noise 'bark'
end
Этот способ немного более эффективен, как и при каждом вызове метода, который вам не нужен, чтобы исследовать класс, чтобы он возвращался (или пересылал?) для константы.
Ответ 5
Если вы хотите, чтобы Object-Oriented Way (TM), то я думаю, вы хотите:
class Animal
# abstract animals cannot make a noise
end
class Dog < Animal
def make_noise
print "bark"
end
end
class Cat < Animal
def make_noise
print "meow"
end
end
d = Dog.new
d.make_noise # prints bark
c = Cat.new
c.make_noise # prints meow
Если вы хотите реорганизовать, чтобы предотвратить дублирование кода для print
:
class Animal
def make_noise
print noise
end
end
class Dog < Animal
def noise
"bark"
end
end
class Cat < Animal
def noise
if friendly
"meow"
else
"hiss"
end
end
end
d = Dog.new
d.make_noise # prints bark
c = Cat.new
c.make_noise # prints meow or hiss