2009-11-14 3 views
103

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

module Rake 
    include Test::Unit::Assertions 

    def run_tests # etc. 
    end 

    # what does the next line do? 
    extend self 
end 

ответ

107

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

+2

Почему такой синглтон более эффективен? – xuuso

26

В модуле само является классом модуля. Так, например

puts self 

вернется Rake так,

extend self 

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

Rake.run_tests 
14

Для меня всегда полезно думать о 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' 
3

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

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

module Rake 
    include Test::Unit::Assertions 

    def run_tests # etc. 
    end 

end 

Rake.extend(Rake) 

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

8

Чтобы избежать ссылки гниль, blog post of Chris Wanstrath, связавшись с пользователем83510, отправляется обратно (с его позволения). Тем не менее, ничто не сравнится с оригиналом, поэтому используйте его ссылку до тех пор, пока оно продолжает работать.


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

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

+0

Другой способ избежать linkrot - использовать что-то вроде машины обратного пути - http://web.archive.org - он хранит историю страниц в Интернете, я нашел его весьма полезным во многих случаях linkrot в любом случае , –