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