класс


этой Ruby Style Guide говорит, что лучше использовать self.method_name вместо class method_name. Но Почему?

class TestClass
  # bad
  class << self
    def first_method
      # body omitted
    end

    def second_method_etc
      # body omitted
    end
  end

  # good
  def self.first_method
    # body omitted
  end

  def self.second_method_etc
    # body omitted
  end
end

есть ли проблемы с производительностью?

6 57

6 ответов:

class << self хорошо держит все ваши методы класса в одном блоке. Если методы добавляются в def self.method С этого момента нет никакой гарантии (кроме соглашения и принятия желаемого за действительное), что позже в файле не будет метода дополнительного класса.

def self.method хорошо явного указания, что метод является методом класса, в то время как с class << self вы должны пойти и найти контейнер самостоятельно.

какой из них более важен для вас является субъективное решение, а также зависит от таких вещей, как сколько других людей работают над кодом и каковы их предпочтения.

как правило, class << self используется в метапрограммировании для установки класса как self в течение длительного периода времени. Если я пытаюсь написать 10 методов, я бы использовал его так:

METHOD_APPENDICES = [1...10]
class << self
  METHOD_APPENDICES.each do |n|
    define_method("method#{n}") { n }
  end
end

это создаст 10 методов (method1, method2, method3 и др.) что бы просто вернуть номер. Я бы использовал class << self для ясности в этом деле, потому что в метапрограммировании self - это важно. Засорение self. внутри было бы на самом деле сделать вещи меньше читаемый.

если вы просто определяете методы класса обычно, придерживайтесь self.class_method_name потому что больше людей могут понять это. Нет необходимости вводить мета-синтаксис, если вы не ожидаете, что ваша аудитория поймет его.

как отмечалось выше, оба стиля кажутся эквивалентными, однако с использованием class << self позволяет пометить методы класса как private или protected. Например:

class UsingDefSelf
  def self.a; 'public class method'; end
  private
  def self.b; 'public class method!'; end
end

class UsingSingletonClass
  class << self
    def a; 'public class method'; end
    private
    def b; 'private class method'; end
  end
end

private влияет только на методы экземпляра. Используя класс singleton, мы определяем методы экземпляра этого класса, которые превращаются в методы класса содержащего класса!

мы также можем отметить методы класса как private С def self:

class UsingDefSelf
  def self.a; 'private class method'; end
  def self.b; 'private class method!'; end
  private_class_method :a, :b
  # In Ruby 2.1 there is an alternative syntax
  private_class_method def self.c; 'private class method!'; end
end

но мы не можем пометить их как protected, нет никакого protected_class_method. (Однако, поскольку class является единственным экземпляром его singletonclass, private class method и protected class Method почти одинаковы, за исключением того, что их синтаксис вызова отличается.)

также он менее проще, чем с помощью class << self Марк private методы класса, так как вы должны перечислить все имена методов в private_class_method или private_class_method для каждого определения метода частного класса.

Я предполагаю, что они думают self.* лучше, потому что вы можете точно сказать, что это метод класса или экземпляра, без необходимости прокручивать и захватывать это class << self строку.

в зависимости от того, что вы хотите. Оба очень ясно для того, что вы делаете. Но я думаю о некоторых рекомендациях для этого.

когда есть только один метод класса, чтобы определить, использовать def self.xxx. Потому что для определения только одного метода увеличение уровня отступа, вероятно, станет помехой.

когда есть более одного метода класса для определения, использовать class << self. Потому что писать def self.xxx,def self.yyy и def self.zzz - это, конечно, повторение. Создайте раздел для данные методы.

когда все методы класса метод класса, можно использовать module С module_function вместо class. Это позволит вам определить функции модуля просто использовать def xxx.

пока вопрос и ответы обсуждают только эти два варианта:

class MyClass
  def self.method_name
    ..
  end
end

class MyClass
  class << self
    def method_name
      ..
    end
  end
end

но вот еще один вариант для рассмотрения методов класса / одноэлементных методов / статических методов / методов, которые работают на уровне класса (или независимо от того, что вы хотите их назвать):

class MyClass
  def MyClass.method_name
    ..
  end
end

Я предпочитаю этот вариант, потому что это более очевидным, что он делает. Определение метода выглядит так же, как это было бы вызвано в вашем коде, и ясно, что он работает с классом уровень.

Я также исхожу из фона Python, где self используется, например, методы, тогда как в Ruby,self используется для методов класса. Это часто смущает меня, поэтому, чтобы не думать "является ли метод self в Ruby методом класса или экземпляра?- Я использую def ClassName.methodname.