Ruby:自己拡張


113

Rubyでは、の基本的な考え方を理解していextendます。しかし、このコードセグメントで何が起こっているのでしょうか。具体的には何をしextendますか?インスタンスメソッドをクラスメソッドにする便利な方法ですか?最初からクラスメソッドを指定するのではなく、なぜこのようにするのですか?

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

  # what does the next line do?
  extend self
end

回答:


115

これは、インスタンスメソッドをクラスメソッドにする便利な方法です。しかし、より効率的なシングルトンとして使用することもできます。


2
なぜそのようなシングルトンの方が効率的ですか?
xuuso 2016年

5
あなたのリンクは私の友達を腐らせました。
Ulysse BN

1
この回答をarchive.orgへのリンクで更新しました
Mike Szyndel

1
それは説明していないので、この答えは不十分でどのように問題になっているキーワードは、クラスメソッドにインスタンスメソッドになります。また、「より効率的なシングルトン」とは何か、またはそれと何が関係するかについても説明していませんextend self
ジェイキ

29

モジュールでは、selfはモジュールクラス自体です。だから例えば

puts self

レーキを返すので、

extend self

基本的に、Rakeで定義されたインスタンスメソッドを使用できるようにするので、

Rake.run_tests

23

私にとってそれは常に考えるのに役立ちますextendようincludeシングルトンクラス(また、メタまたは固有クラスとして知られている)の内部。

シングルトンクラス内で定義されたメソッドは基本的にクラスメソッドであることをご存じでしょう。

module A
  class << self
    def x
      puts 'x'
    end
  end
end

A.x #=> 'x'

今、私たちは、それを知っているextendだろうincludeので、シングルトンクラスの内部およびモジュール内のメソッドは、クラスメソッドとして公開します:

module A
  class << self
    include A

    def x
      puts 'x'
    end
  end

  def y
    puts 'y'
  end
end

A.x #=> 'x'
A.y #=> 'y'

15

リンクの腐敗を避けるために、user83510によってリンクされたChris Wanstrathのブログ投稿が(彼の許可を得て)以下に再投稿されています。それでも、オリジナルに勝るものはないので、機能し続ける限り彼のリンクを使用してください。


→singin 'singletons 2008年11月18日わからないことがある。たとえば、David Bowie。または南半球。しかし、Rubyのシングルトンのように私の心を揺るがすものは何もありません。本当に、それは完全に不必要だからです。

これは、あなたがあなたのコードであなたにしてほしいことです:

require 'net/http'

# first you setup your singleton
class Cheat
  include Singleton

  def initialize
    @host = 'http://cheat.errtheblog.com/'
    @http = Net::HTTP.start(URI.parse(@host).host)
  end


  def sheet(name)
    @http.get("/s/#{name}").body
  end
end

# then you use it
Cheat.instance.sheet 'migrations'
Cheat.instance.sheet 'yahoo_ceo'

しかし、それはクレイジーです。力と戦ってください。

require 'net/http'

# here's how we roll
module Cheat
  extend self

  def host
    @host ||= 'http://cheat.errtheblog.com/'
  end

  def http
    @http ||= Net::HTTP.start(URI.parse(host).host)
  end

  def sheet(name)
    http.get("/s/#{name}").body
  end
end

# then you use it
Cheat.sheet 'migrations'
Cheat.sheet 'singletons'

なぜでしょうか?APIはより簡潔であり、コードのテスト、モック、およびスタブの実行が容易であり、必要に応じて適切なクラスに変換するのは簡単です。

((著作権は10クリスwanstrathであるべきです))


linkrotを回避するもう1つの方法は、ウェイバックマシン(web.archive.org)のようなものを使用することです。これは、web全体のページの履歴を保持します。いずれにせよ、linkrotの多くの場合に非常に役立ちます。
Kem Mason 2013

3

extend self既存のすべてのインスタンスメソッドがモジュールメソッドとして含まれます。これは言うことと同じextend Rakeです。また、RakeクラスのオブジェクトですModule

同等の動作を実現する別の方法は次のとおりです。

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

end 

Rake.extend(Rake)

これは、プライベートメソッドで自己完結型モジュールを定義するために使用できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.