Во-первых, отчасти причина того, что ваш пример кода не работает для вас, заключается в том, что у вас есть две разные @people
переменные - одна - переменная экземпляра , а другая - класс переменная экземпляра .
class Example
# we're in the context of the Example class, so
# instance variables used here belong to the actual class object,
# not instances of that class
self.class #=> Class
self == Example #=> true
@iv = "I'm a class instance variable"
def initialize
# within instance methods, we're in the context
# of an _instance_ of the Example class, so
# instance variables used here belong to that instance.
self.class #=> Example
self == Example #=> false
@iv = "I'm an instance variable"
end
def iv
# another instance method uses the context of the instance
@iv #=> "I'm an instance variable"
end
def self.iv
# a class method, uses the context of the class
@iv #=> "I'm a class instance variable"
end
end
Если вы хотите создать переменные один раз в классе для использования в методах экземпляра этого класса, используйте constants
или class variables
.
class Example
# ruby constants start with a capital letter. Ruby prints warnings if you
# try to assign a different object to an already-defined constant
CONSTANT_VARIABLE = "i'm a constant"
# though it's legit to modify the current object
CONSTANT_VARIABLE.capitalize!
CONSTANT_VARIABLE #=> "I'm a constant"
# class variables start with a @@
@@class_variable = "I'm a class variable"
def c_and_c
[ @@class_variable, CONSTANT_VARIABLE ] #=> [ "I'm a class variable", "I'm a constant" ]
end
end
Несмотря на это, в контексте вашего кода вы, вероятно, не хотите, чтобы все ваши экземпляры Family_Type1 ссылались на одни и те же полицейских и бухгалтеров, верно? Или ты?
Если мы перейдем к использованию переменных класса:
class Family_Type1
# since we're initializing @@people one time, that means
# all the Family_Type1 objects will share the same people
@@people = [ Policeman.new('Peter', 0), Accountant.new('Paul', 0), Policeman.new('Mary', 0) ]
def initialize(*ages)
@@people.zip(ages).each { |person, age| person.age = age }
end
# just an accessor method
def [](person_index)
@@people[person_index]
end
end
fam = Family_Type1.new( 12, 13, 14 )
fam[0].age == 12 #=> true
# this can lead to unexpected side-effects
fam2 = Family_Type1.new( 31, 32, 29 )
fam[0].age == 12 #=> false
fam2[0].age == 31 #=> true
fam[0].age == 31 #=> true
Инициализация во время выполнения может быть выполнена с помощью метапрограммирования, как сказал Чирантан, но если вы инициализируете только несколько классов и знаете, как их зовут, вы также можете сделать это, просто используя то, что вы читаете из файла: 1019 *
PARAMS = File.read('params.csv').split("\n").map { |line| line.split(',') }
make_people = proc do |klasses, params|
klasses.zip(params).map { |klass,name| klass.new(name, 0) }
end
class Example0
@@people = make_people([ Fireman, Accountant, Fireman ], PARAMS[0])
end
class Example1
@@people = make_people([ Butcher, Baker, Candlestickmaker ], PARAMS[0])
end