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

时间:2020-02-13 08:41:57

标签: ruby instance-variables class-variables

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

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

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

我有两个类变量:信息(进口商信息)和模式(json模式)。

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

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

schema = PARENTCLASS.schema.deep_merge({

代替

schema = parentImporter .schema.deep_merge({

super(params,THISCLASS.schema)

代替

super(params, childImporter .schema)。

有没有办法做到这一点?

当前,如果我尝试

super(params,@@ schema)

我明白了

NameError:childImporter中未初始化的类变量@@ schema

谢谢

2 个答案:

答案 0 :(得分:4)

我想知道是否有一种方法不对类名称childImporter和parentImporter进行硬编码,而是使用对父类的引用,例如具有

schema = PARENTCLASS.schema.deep_merge({

代替

schema = parentImporter.schema.deep_merge({

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

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既是类方法又是其父类的实例方法。在这两种变体中,您都可以简单地调用super来调用父级的实现:

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的值,这样就不会在每次调用方法时都重新创建它们:

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是所谓的类实例变量,即类对象范围内的实例变量。它们的行为与临时实例中的实例变量完全相同。特别是,@infos中的ParentImporterChildImporter中的super(params,THISCLASS.schema) 之间没有联系。


super(params,childImporter.schema).

代替

importer = ChildImporter.new

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

要获取对象的类,可以调用其class方法:

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

在实例方法中也是如此:

class

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


底部注释:我根本不会使用$.when( $.getScript("https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"), $.getScript("https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.js"), $.getScript("1.js"), $.getScript("2.js"), $.getScript("3.js"), $.Deferred(function(deferred) { $(deferred.resolve); }) ).done(function() { $('input[name=\'time\']').daterangepicker(); }); 类变量。只需调用您的类方法即可。

答案 1 :(得分:0)

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

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

这将打印

孩子

父母