Рубин: расширить себя - PullRequest
       25

Рубин: расширить себя

113 голосов
/ 14 ноября 2009

В Ruby я понимаю основную идею extend. Однако, что происходит в этом сегменте кода? В частности, что делает extend? Это просто удобный способ превратить методы экземпляра в методы класса? Почему вы делаете это таким образом, а не определяете методы класса с самого начала?

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

  # what does the next line do?
  extend self
end

Ответы [ 5 ]

114 голосов
/ 14 ноября 2009

Это удобный способ превратить методы экземпляра в методы класса. Но вы также можете использовать его как более эффективный синглтон .

29 голосов
/ 14 ноября 2009

В модуле self - это сам класс модуля. Так например

puts self

вернет рейк итак,

extend self

в основном делает методы экземпляра, определенные в Rake, доступными для него, так что вы можете сделать

Rake.run_tests
21 голосов
/ 23 июля 2012

Для меня всегда полезно думать о 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'
14 голосов
/ 23 сентября 2012

Чтобы избежать гниения ссылок, блог Криса Ванстрата , на который ссылается user83510, находится ниже (с его разрешения) Тем не менее, ничто не сравнится с оригиналом, поэтому используйте его ссылку, пока она продолжает работать.


→ поющие синглтоны 18 ноября 2008 г. Есть вещи, которые я просто не понимаю. Дэвид Боуи, например. Или Южное полушарие. Но ничто так не поражает, как сингл Руби. Потому что на самом деле это совершенно не нужно.

Вот что они хотят, чтобы вы сделали с вашим кодом:

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 более лаконичен, код легче тестировать, макетировать и заглушать, и до сих пор его очень просто преобразовать в соответствующий класс в случае необходимости.

((авторское право должно быть десятью крисом Вантстратом))

3 голосов
/ 30 июля 2012

extend self включает все существующие методы экземпляра как методы модуля. Это эквивалентно высказыванию extend Rake. Также Rake является объектом класса Module.

Другим способом достижения эквивалентного поведения будет:

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

end 

Rake.extend(Rake)

Это можно использовать для определения автономных модулей с закрытыми методами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...