класс
этой 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 ответов:
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
.