在Ruby中动态创建类

前端之家收集整理的这篇文章主要介绍了在Ruby中动态创建类前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个类应该看起来像这样:
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

猜你在找的Ruby相关文章