クラスメソッドのalias_methodはありますか?


10

次のクラスを考えてみましょう:

class Foo
  def an_inst_method
    'instance method'
  end

  def self.a_class_method
    'class method'
  end

  alias_method :a_new_inst_method, :an_inst_method
end

これは問題ではなく、問題なく呼び出すことができますFoo.new.a_new_inst_method

のようなクラスメソッドFoo.add_widget(*items)とエイリアスを設定して、次のようなことができるようにしたいと思います。

Foo.add_widget 'item1'
Foo.add_widgets 'item2', 'item3'

以下のようなので、基本的には「ルビースタイル」を持っている1.minute2.minutes私はエイリアスにしたいので、Foo.add_widgetその呼び出しFoo.add_widgetsの呼び出しとまったく同じ方法を。私はそれをラップできることを知っていますが、私はこれをよりきれいな方法で行うことができるはずだと感じています。

次のようなことを試してみてください。

class Foo
  def an_inst_method
    'instance method'
  end

  def self.a_class_method
    'class method'
  end

  alias_method :a_new_inst_method, :an_inst_method
  alias_method :a_new_class_method, :a_class_method
end

ただし、次のエラーが発生します。

NameError (undefined method `a_class_method' for class `Foo')

したがって、これはクラスメソッドでは機能しないようです。これを行うにはどうすればよいですか?

回答:


9

alias_methodレシーバーのインスタンスメソッドにエイリアスを設定します。クラスメソッドは、実際にはクラスシングルトンクラスで定義されたインスタンスメソッドです。

class MyClass
  def self.a
    "Hello World!"
  end
end

method_1 = MyClass.method(:a).unbind
method_2 = MyClass.singleton_class.instance_method(:a)

method_1 == method_2
#=> true

シングルトンクラスで定義されたインスタンスメソッドにエイリアスを設定するには、class << object構文を使用して開くことができます。

class << MyClass
  alias_method :b, :a
end

MyClass.b
#=> "Hello World!"

または、singleton_classメソッドを使用して直接参照することもできます。

MyClass.singleton_class.alias_method :c, :a

MyClass.c
#=> "Hello World!"

クラスコンテキスト内にいる場合は、クラスselfを参照します。したがって、上記は次のように書くこともできます。

class MyClass
  class << self
    def a
      "Hello World!"
    end
    alias_method :b, :a
  end
end

または

class MyClass
  def self.a
    "Hello World!"
  end
  singleton_class.alias_method :c, :a
end

または、2つの組み合わせ。


5

クラスメソッドとそのalias_method呼び出しを別のモジュールにラップし、そのモジュールを次の方法でクラスに組み込むことができますextend

class Foo
  def an_inst_method
    'instance method'
  end
  alias_method :a_new_inst_method, :an_inst_method

  module ClassMethods
    def a_class_method
      'class method'
    end
    alias_method :a_new_class_method, :a_class_method
  end

  extend ClassMethods
end

おい!extend ClassMethods解決策を忘れてしまいました。+1
アーロナ

4

理解しておくべき重要なことは、Rubyにはクラスメソッドなどは存在しないということです

クラスメソッドは、実際には単なるシングルトンメソッドです。クラスメソッドについて特別なことは何もありません。すべてのオブジェクトはシングルトンメソッドを持つことができます。Class「のインスタンスのシングルトンメソッドClass」が長すぎて扱いにくいため、オブジェクトがaの場合は、単に「クラスメソッド」と呼びます。

待つ!「シングルトン法」って言った?

もう1つ重要なことは、Rubyにはシングルトンメソッドなどは存在しないということです

シングルトンメソッドは、実際にはシングルトンクラスの通常の退屈な古いインスタンスメソッドです。シングルトンメソッドには特別なものはありません。これらは他のインスタンスメソッドと同様に、単なるインスタンスメソッドです。

実際、Rubyにはインスタンスメソッドしかありません。関数、コンストラクター、静的メソッド、クラスメソッド、モジュール関数、シングルトンメソッドはありません。

問題は、「これはクラスメソッドか、これはシングルトンメソッドか」ではなく、「このメソッドがどのモジュールで定義されているか」です。

「シングルトンメソッド」は、実際にはシングルトンクラスで定義されたインスタンスメソッドです。のシングルトンクラスにアクセスするための構文は次のとおりfooです。

class << foo
end

Object#singleton_classオブジェクトのシングルトンクラスを返すメソッドもあります。

すべてのメソッドがインスタンスメソッドであり、クラスメソッドが存在しないという事実について、なぜ私はそれほど積極的に攻撃していますか?Rubyのオブジェクトモデルは、人々が思っているよりもはるかに単純であることを意味します。結局のところ、あなたの質問では、インスタンスメソッドにエイリアスを設定する方法はわかっていることを既に示していますが、クラスメソッドにエイリアスを設定する方法がわからないとしています。しかし、それは間違っています!あなたはないので、どのようにエイリアスクラスのメソッドを知っている彼らは、インスタンスメソッドです。この事実を正しく教えられていたなら、この質問をする必要はなかっただろう!

すべてのメソッドがインスタンスメソッドであり、「シングルトンメソッド」と呼ばれるものがシングルトンクラスのインスタンスメソッドにすぎないことを理解すると、解決策が明らかになります。

singleton_class.alias_method :a_new_class_method, :a_class_method

注:上記で「Xのようなものは存在しない」と書いたとき、私が言ったのは「Ruby言語では Xのようなものは存在しない」ということです。これは、それらの概念がRubyコミュニティに存在しないという意味ではありませ

私たちは、定期的に、それは「シングルトンクラスのインスタンスメソッド」またはのインスタンスであることを起こるオブジェクトのシングルトンクラスの「インスタンスメソッドの話よりも簡単であるという理由だけで、「シングルトンメソッド」と「クラスメソッド」について話Classクラス」以下のようにも方法がありObject#define_singleton_methodObject#singleton_methodObject#singleton_methodsModule#private_class_methodModule#public_class_method、およびModule#module_functionRubyのコアライブラリでは。しかし、それらは言語の概念ではないことを覚えておくことが常に重要です。これらは私たちの頭といくつかのライブラリメソッドの名前にのみ存在するコミュニティの概念です。


2

OK、私はこのようなことができるように見え、うまくいくでしょう:

class Foo
  def an_inst_method
    'instance method'
  end

  def self.a_class_method
    'class method'
  end

  alias_method :a_new_inst_method, :an_inst_method

  class << self
    alias_method :a_new_class_method, :a_class_method
  end
end

Foo.a_class_method # => "class method" 
Foo.a_new_class_method # => "class method"

ここにRuby言語に関する有用な情報があり、包括的な回答を送信したい場合は、+ 1を差し上げます。


1
あなたがないときclass << selfに続いてalias_method :a_new_class_method, :a_class_method、あなた実際に呼び出すalias_methodのシングルトンクラス時Foo。これを書くもう1つの方法はsingleton_class.alias_method :a_new_class_method, :a_class_method、クラスのコンテキスト内です。
3limin4t0r

あなたは答えから何がもっと欲しいですか?つまり、これはおそらく最もクリーンなソリューションです。
デイブニュートン

@ 3limin4t0rもしあなたがそれを答えたら、私はそれを+1します。この追加情報をありがとう。
aarona

@DaveNewtonあなたは正しいですが、間接的に問題を解決したとしても、誰かが問題にもっと意味のある情報を提供できるなら、私もそれは報われるべきだと私は哲学を持っているので。
aarona

2

alias_methodインスタンスで動作するため、1レベル深くしてClassインスタンスまたはクラスのメタクラスで動作する必要があります。Rubyには、一種の頭痛の種となる可能性のあるワイルドオブジェクトモデルがありますが、次のような強力な機能も提供します。

class Foo
  def an_inst_method
    'instance method'
  end

  alias_method :a_new_inst_method, :an_inst_method

  class << self
    def a_class_method
      'class method'
    end

    alias_method :a_new_class_method, :a_class_method
  end
end

私は約10年間、railsのコンテキストでルビーを使用してきましたが、つい最近になって、オブジェクトモデルの詳細な調査を開始しました。素敵なものがたくさんあります!
aarona
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.