ruby :如何避免对 类 名称进行硬编码?

ruby : how can I avoid hardcoding the classes names?

我正在学习 Ruby 以及 class 变量和实例变量之间的区别。

我正在编写一段代码,其中有(很多)classes 继承了其他 classes。

class childImporter < parentImporter

  def self.infos
    parentImporter.infos.merge({
      :name=>           'My Importer',
    })
  end

  def self.schema
    schema = parentImporter.schema.deep_merge({
      'selectors' => {
        'track' => {
          'artist'=>  {'path'=>{'default'=>'//creator'}},
          'title'=>   {'path'=>{'default'=>['//name'}},
        }
      }
    })

    @@schema = schema
  end


  def initialize(params = {})
    super(params,childImporter.schema)
  end

end

我有两个 class 变量:infos(进口商信息)和 schema(json 模式) .

我需要它们能够在实例之外获取它们(这就是为什么它们是 class 变量),并成为它们父值的扩展(这就是为什么我 deep_merge 他们)和

我的示例确实有效,但我想知道是否有一种方法可以不对 classes 名称 childImporter 和 parentImporter 进行硬编码,而是使用对父 class 的引用,例如具有

schema = PARENTCLASS.schema.deep_merge({

而不是

schema = parentImporter.schema.deep_merge({

super(params,THISCLASS.schema)

而不是

super(params,childImporter.schema).

有办法实现吗?

目前,如果我尝试

super(params,@@schema)

我明白了

NameError: uninitialized class variable @@schema in childImporter

谢谢

这可能会有所帮助 - 您可以像这样访问 class 和 superclass:

 class Parent
    
 end
    
 class Child < Parent
    
   def self.print_classes
     p itself
     p superclass
   end
  end
    
 Child.print_classes

这将打印

Child

Parent

I wonder if there is a way not to hardcode the classes names childImporter and parentImporter and rather use a reference to the parent class, for example having

schema = PARENTCLASS.schema.deep_merge({

instead of

schema = parentImporter.schema.deep_merge({

您正在寻找的方法是 superclass – 它 returns 接收者的 parent class。在 class 主体或 class 方法中,您可以在没有显式接收者的情况下调用它:

class ParentImporter
  def self.infos
    { name: 'Parent Importer', type: 'Importer' }
  end
end

class ChildImporter < ParentImporter
  def self.infos
    superclass.infos.merge(name: 'Child Importer')
  end
end

ParentImporter.infos #=> {:name=>"Parent Importer", :type=>"Importer"}
ChildImporter.infos  #=> {:name=>"Child Importer", :type=>"Importer"}

但还有更简单的方法。 类 inherit class 方法和 parent class 中的实例方法。在这两种变体中,您只需调用 super 即可调用 parent 的实现:

class ChildImporter < ParentImporter
  def self.infos
    super.merge(name: 'Child Importer')
  end
end

ParentImporter.infos #=> {:name=>"Parent Importer", :type=>"Importer"}
ChildImporter.infos  #=> {:name=>"Child Importer", :type=>"Importer"}

此外,您可能想要 memoize 值,这样它们就不会在每次调用方法时都 re-created:

class ParentImporter
  def self.infos
    @infos ||= { name: 'Parent Importer', type: 'Importer' }
  end
end

class ChildImporter < ParentImporter
  def self.infos
    @infos ||= super.merge(name: 'Child Importer')
  end
end

那些@infos是so-calledclass实例变量,即class[=范围内的实例变量67=](s)。它们的行为与偶然实例中的实例变量完全一样。特别是,ParentImporter 中的 @infosChildImporter 中的 @infos 之间没有任何联系。


or

super(params,THISCLASS.schema)

instead of

super(params,childImporter.schema).

要获得 object 的 class,您可以调用它的 class 方法:

importer = ChildImporter.new

importer.class       #=> ChildImporter
importer.class.infos #=> {:name=>"Child Importer", :type=>"Importer"}

在实例方法中同样有效:

  def initialize(params = {})
    super(params, self.class.schema)
  end

请注意,class 方法必须始终使用显式接收器调用。省略接收器并只写 class.schema 会导致错误。


底注:我根本不会使用 @@ class 变量。只需调用您的 class 方法即可。