我有一个类应该看起来像这样:
class Family_Type1 @people = Array.new(3) @people[0] = Policeman.new('Peter',0) @people[1] = Accountant.new('Paul',0) @people[2] = Policeman.new('Mary',0) def initialize(*ages) for i in 0 ... @people.length @people[i].age = ages[i] end end end
我希望能够在运行时定义一些类似这样的类(在启动时定义它们),其中数组的大小和分配给每个参数的类型在运行时由外部规范文件定义.
我有点使用evals工作,但这真的很丑陋.有什么更好的方法吗
解决方法
首先,您的示例代码不适合您的一部分原因是您有两个不同的@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
如果要在类中创建变量一次以在该类的实例方法中使用,请使用常量或类变量.
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',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
如Chirantan所说,运行时初始化可以通过元编程来完成,但是如果你只是初始化几个类,并且知道他们的名字,你也可以通过使用从文件中读取的任何东西来做:
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