Рубін: розширити себе


113

У Рубі я розумію основну ідею 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

5
Ваше посилання гнило мого друга.
Уліссе БН

1
Оновлено цю відповідь посиланням на archive.org
Майк Шендел

1
Ця відповідь є недостатньою, оскільки не пояснює, як саме ключове слово перетворює методи екземпляра в методи класу. Це також не пояснює, що таке "більш ефективний синглтон", або що extend selfз цим пов'язано.
jayqui

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

Щоб уникнути гниття посилань, повідомлення про блог Кріса Ванстрата, пов’язане користувачем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 більш стислий, код простіший для тестування, макетування та заглушки, і його все ще просто просто перетворити в належний клас, якщо виникне потреба.

((авторські права повинні десять крис wanstrath))


Ще один спосіб уникнути linkrot - це використовувати щось на кшталт зворотної машини - web.archive.org - він зберігає історію сторінок у мережі, я вважаю це досить корисним у багатьох випадках linkrot так чи інакше.
Кем Мейсон

3

extend selfвключає всі існуючі методи екземпляра як модульні методи. Це рівносильно сказати extend Rake. Також Rakeє об’єктом класу Module.

Іншим способом досягнення еквівалентної поведінки буде:

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

end 

Rake.extend(Rake)

Це можна використовувати для визначення самостійних модулів з приватними методами.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.