ruby: как я могу избежать жесткого кодирования имен классов? - PullRequest
0 голосов
/ 13 февраля 2020

Я изучаю 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 ( {

вместо

схема = parentImporter .schema.deep_merge ({

или

супер (params, THISCLASS.schema)

вместо * 10 36 *

super (params, childImporter .schema).

Есть ли способ добиться этого?

В настоящее время, если я try

super (params, @@ schema)

Я получаю

NameError: неинициализированная переменная класса @@ schema в childImporter

Спасибо

Ответы [ 2 ]

4 голосов
/ 13 февраля 2020

Интересно, есть ли способ не жестко кодировать имена классов 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"}

Но есть еще более простой способ. Классы наследуют как методы класса, так и методы экземпляра от своего родительского класса. И в обоих вариантах вы можете просто вызвать 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"}

Кроме того, вы можете запомнить значения, чтобы они не создавались заново. каждый раз при вызове методов:

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 в ParentImporter и тем в ChildImporter.


или

super(params,THISCLASS.schema)

вместо

super(params,childImporter.schema).

Чтобы получить класс объекта, вы можете вызвать его метод 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 приводит к ошибке.


Примечание: я бы вообще не использовал переменные класса @@. Просто вызовите методы вашего класса.

0 голосов
/ 13 февраля 2020

Это может помочь - вы можете получить доступ к классу и суперклассу следующим образом:

 class Parent

 end

 class Child < Parent

   def self.print_classes
     p itself
     p superclass
   end
  end

 Child.print_classes

Это напечатает

Child

Parent

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...