2012-06-09 7 views
55

Ruby Style Guideは、class method_nameの代わりにself.method_nameを使用したほうがよいことを示しています。しかし、なぜ?クラス<<自己対Rubyのself.method:何が良いですか?

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 

パフォーマンスに問題はありますか?

+14

添付の説明がない場合は、真剣にスタイルの提案をするのは難しいですね。 –

+3

「これはGitHub._の内部で独自のルビーアプリケーション用に使用するガイドです」ということに注意してください。つまり、これはGithubが独自に定義したスタイルです。 Rubyスタイルを修正するための決定的なガイドではありません。 –

+1

私は同意しますが、権威のある熟練したRubyistsから書かれたようです。 –

答えて

75

class << selfは、すべてのクラスメソッドを同じブロックに保持するのに適しています。メソッドがdef self.methodに追加されている場合は、後でファイルに追加のクラスメソッドが追加されないという保証はありません。

def self.methodは、メソッドがクラスメソッドであることを明示的に示していますが、class << selfではコンテナを自分で見つけなければなりません。

これらのうち重要なものは主観的な決定であり、他の人がコード上で何人を作業しているか、好みが何であるかなどによっても異なります。

+6

私はそれに反して、これは単純な個人的な選択ではありません。 '<<'を使うことにはコードの可読性が欠点です - @ Flexoidの答えを見てください。 'class << self'構文の欠点とコードブロックを使うことは、ブロックがいくつかのメソッドよりも長い場合、' class <<までスクロールしない限り、これらのメソッドがクラスメソッドであることは明らかではありません自己セクション。 –

+1

それは 'class << self'に特有の問題ではありません。私は深いモジュールネストを持つたくさんのソースファイル(より多くの場合、大規模で重要ではないプロジェクト)を見てきましたが、スクロールアップするまでは明確ではありません。 – Gareth

+0

@DmitriZagidulinこの場合、メソッドはインデントに基づくクラスメソッドです。 – weakish

5

self.*は、確かに言うことができるので、クラスまたはインスタンスメソッドだと思うと思うと思いますが、このclass << self文字列をスクロールアップして綴じる必要はありません。

+1

私はこの質問に対する他の答えに驚いています。これを行うには、これは誠実な方法です。 'class << self'を書くと、メソッドがクラスメソッドであることが読者に分かります。a)少数しかありません。* AND * b)' class << self'行は現在あなたのエディタに表示されます。また、 'def self.thing'の規則に従えば、クラスメソッドとインスタンスメソッドのgrepも簡単です。 Dave Thomasは 'self 'を(ブロック内で、例えばクラスのattr_accessorを呼び出すために)変更する必要があるときに予約することを提案しています。 –

+1

その時点で、私的な方法を持つことは "読むことができない"のと同じでしょうか?それらはすべて「プライベート」キーワードの下にインデントされているためです。私はRubyではすべてのメソッドに対して "private:method"を明示的に呼び出すことができますが、C構文がどのように機能するかを考えると、関数/メソッド定義にコンテキストがあることを開発者が知っているとは思わないと思います。 –

28

一般的に、class << selfは、クラスを長時間自己に設定するためにメタプログラミングに使用される。私は10のメソッドを書くしようとしている場合は、私はそうのようにそれを使用します。

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

これは単に数を返します10個の方法(法1、方法2、法3など)を作成します。がメタプログラミングで重要であるため、私はclass << selfを明瞭にするために使用します。そこにくぼみself.が実際にはより少なくてのものを作るでしょう。

通常クラスメソッドを定義している場合は、より多くの人が理解する可能性が高いため、self.class_method_nameに固執してください。あなたの聴衆がそれを理解することを期待しない限り、メタ構文を持たせる必要はありません。

+0

Imho、最高の答え。しかし、Rubyがクラスメソッドを定義するための2つの構文スタイルを持っていることに非主観的な理由があります。 – 18augst

3

あなたが好きな方。両方ともあなたがしていることに対して非常に明確です。しかし、私はこれについていくつかの提案を考えています。

定義するクラスメソッドが1つのみの場合は、を使用してください。def self.xxx。ただ1つのメソッドを定義するために、インデントレベルを上げるとおそらく乱雑になります。

定義するクラスメソッドが複数ある場合は、class << selfを使用します。 def self.xxxdef self.yyydef self.zzzを書くのは確かに繰り返しです。これらのメソッドのセクションを作成します。

クラスのすべてのメソッドは、クラスメソッドです

あなたは module_functionの代わり classmoduleを使用することができます。これにより、モジュール関数を定義することができます。 def xxxを使用します。

+1

'extend self'はクラスでは動作しません。 –

+0

コメントありがとうございます。私は答えを決めた。 – nonowarn

19

上記のように、両方のスタイルは同等ですが、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は、インスタンスメソッドにのみ影響します。シングルトンクラスを使用して、そのクラスのインスタンスメソッドを定義しています。これは、そのクラスを含むクラスのメソッドに変わります!

我々はまた、def selfprivateとしてクラスメソッドをマークすることができます。

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はそのシングルトンクラスの唯一のインスタンスなので、プライベートクラスメソッドと保護されたクラスメソッドは、呼び出し構文が異なる以外はほとんど同じです)

またを使用してprivateクラスメソッド、 private_class_methodにすべてのメソッド名をリストするか、接頭語private_class_methodをすべてのプライベートクラスメソッド定義にリストする必要があるからです。

-1

これまでの質問と回答は、これらの2つのオプションについて説明します

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が使用されています。これはしばしば私を混乱させるので、 "Rubyのクラスメソッドまたはインスタンスメソッドの自己メソッドですか?"私はdef ClassName.methodnameを使用します。

+0

"Rubyではselfがクラスメソッドに使われていたのに対し、selfはインスタンスメソッドに使われるPythonのバックグラウンドもあります。"これはRubyの "class"が "インスタンス"であるためです。 Pythonのインスタンスメソッドでは 'def m(self、args):'、Rubyはdef(args)( "self"と ":"を省略)です。 – weakish

+2

このスタイルは使用しないでください。ルビーは、非常に有名なコミュニティのある言語です。これにより、開発者はあまり説明しなくても、またはを物事に並べてコード化することができます。これは独自の独自の基準を設定するだけです。 –

+0

@AditSaxenaはあなたのプロジェクト/チームのためのスタイルガイドを持っています。 (FWIWでは、私はRubyでほぼ独占的にプログラムして以来、私が提案したオプションを使用しなくなり、 'self'に慣れてきましたが、さまざまなオプションについては知っています。) – Dennis

関連する問題