Po pierwsze, część z tego powodu Twój przykładowy kod nie pracuje dla Ciebie jest to, że masz dwa różne @people
zmienne - jeden jest instancja zmiennej a drugi jest instancją klasy zmienna.
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
Jeśli chcesz utworzyć zmiennych jeden raz w klasie do wykorzystania w metodach instancji tej klasy, należy constants
lub 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
Mimo to, w kontekście swojego kodu, to prawdopodobnie nie chcą wszystkie instancje Family_Type1 odnoszą się do tych samych policjantów i Księgowych prawda? A może ty?
Jeśli przełączyć się za pomocą zmiennych Klasa:
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
Inicjalizacja Runtime można zrobić z metaprogramowanie, jak Chirantan powiedział, ale jeśli inicjowania tylko kilka klas, i wiesz co ich nazwa jest możesz to również zrobić za pomocą tego, co czytasz z pliku:
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
Jest to jedyna odpowiedź, która naprawdę wyjaśnia całą sytuację IMO. – Chuck
niesamowite wyjaśnienie, pomaga w usuwaniu koncepcji ... thnks –