Яка різниця між включати та вимагати в Ruby?


465

Моє запитання схоже на " Яка різниця між включенням і розширенням в Ruby? ".

Яка різниця між requireі includeв Ruby? Якщо я просто хочу використовувати методи з модуля в своєму класі, я повинен requireце чи includeце?


1
Для чого це коштує, ось посилання на документацію спільноти для requireі include, а також відповідних, Module#append_features.

Відповіді:


543

Яка різниця між "включати" та "вимагати" в Ruby?

Відповідь:

Методи включати і вимагати дуже різні речі.

Метод вимагає виконувати те, що включає в себе в більшості інших мов програмування: запустіть інший файл. Він також відстежує те, що вам потрібно в минулому, і не буде вимагати одного і того ж файлу двічі. Для запуску іншого файлу без цієї додаткової функціональності можна скористатися методом завантаження.

Метод include включає всі методи з іншого модуля і включає їх у поточний модуль. Це річ на рівні мови, на відміну від речі на рівні файлу, як з вимогою. Метод include - це основний спосіб "розширити" класи іншими модулями (зазвичай їх називають сумішами). Наприклад, якщо ваш клас визначає метод "кожен", ви можете включити змішаний модуль Enumerable і він може виступати як колекція. Це може заплутати, оскільки дієслово include включається в інших мовах дуже по-різному.

Джерело

Тож якщо ви просто хочете використовувати модуль, а не розширювати його чи робити суміш, тоді ви хочете використовувати require.

Як не дивно, Рубі requireаналогічна Кассіопеяне include, в той час як Рубі includeмайже нічого , як Кассіопеяне include.


45
Насправді C включає, що не завантажує файл, як вимагають, а замість цього рядка #include змінює файл. Файли, що включаються, не повинні бути "заголовками", а #include не повинні бути на початку файлу, але можуть бути де завгодно, як у класі чи навіть у визначенні методу. Це означає, що ви можете робити mixin в C ++, записавши деякі файли у файл і включити його до коду класу, саме так, як ви зробили б у рубіні. Таким чином, вони не так вже й далеко, хоча це справді не є звичайною практикою в С.
mb14

13
Ця відповідь може принести користь, якщо включити приклади.
Ведмідь Тревіс

12
Коментар mb14 має на увазі це, але він чітко заявляє: всупереч тому, що йдеться у відповіді, вимога не «запускає» файл, а завантажує його так, ніби він був частиною файлу, що містить. Це може здатися семантичним занизуванням, але насправді це досить важлива різниця.
Lonny Everyus

Чудове пояснення. Дякуємо за те, що заздалегідь висловили точку з останньою заявою: "Як не дивно, вимога Ruby є аналогічною тому, що включає C, в той час як Ruby включає майже нічого, як і C".
ArtSabintsev

1
@GregSchmit: includeу Ruby це просто спадщина. class C; include M endскладає Mнадклас Cі (колишній) надклас Cнадкласу M. Я не думаю, що C includeпрацює через спадкування, я думаю, що це проста текстова / лексична підміна.
Йорг W Міттаг

100

Якщо ви використовуєте модуль, це означає, що ви вводите всі методи у свій клас. Якщо ви extendкласуєте з модулем, це означає, що ви «вводите» методи модуля як методи класу . Якщо ви includeкласуєте з модулем, це означає, що ви «привносите» методи модуля як методи екземпляра .

EX:

 module A
   def say
     puts "this is module A"
   end
 end

 class B
   include A
 end

 class C
   extend A
 end

B.say => невизначений метод "сказати" для B: Class

B.new.say => це модуль A

C.say => це модуль A

C.new.say => невизначений метод "сказати" для C: Class


23
Я думаю, це не відповідає на питання, але це те, що я шукав =)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

2
Це на самому ділі не відповідає на питання про те, що відмінності між requireі includeє.

94

З книги "Метапрограмування" Ruby,

require()Метод дуже схожий load(), але це означало для різних цілей. Ви використовуєте load()для виконання коду, а ви require()імпортуєте бібліотеки.


73
Оновлення за те, що у вашій відповіді не порівнювали іншу мову :)
Stevo

Проголосуйте за те, щоб не надати відповіді в контексті запитання: "Якщо я просто хочу використовувати методи з модуля в своєму класі?"
benc

57
  • Ruby requireбільше схожий на "включити" в інших мовах (наприклад, на C). Це повідомляє Ruby, що ви хочете внести вміст іншого файлу . Подібними механізмами в інших мовах є:

  • Ruby include- об'єктно-орієнтований механізм успадкування, який використовується для міксинів .

Існує гарне пояснення тут :

[Простий] відповідь полягає в тому, що вимагати і включати по суті не пов'язані між собою.

"вимагати" схожий на C include, що може спричинити плутанину новачка. (Одна помітна відмінність полягає в тому, що місцеві жителі всередині потрібного файлу "випаровуються", коли вимога виконана.)

Ruby include - це не що інше, як C include. Включити оператор "змішує" модуль у клас. Це обмежена форма багаторазового успадкування . Модуль, що входить в комплект, буквально дарує відносини "є-а" на річ, включаючи її.

Акцент додано.


7

Ви коли-небудь пробували requireмодуль? Які були результати? Просто спробуйте:

MyModule = Module.new
require MyModule # see what happens

Модулі не потрібно вимагати, лише вони входять!


Твердження тут невірне. Модулі можуть знадобитися. І кожен, хто працює з наведеним вище кодом, виявить, що отримав той самий результат ( TypeError), якщо слово Moduleбуде змінено на Class.
pjd

7

З програмування Ruby 1.9

Ми зробимо пару пунктів щодо оператора включення, перш ніж продовжувати. По-перше, це не має нічого спільного з файлами. Програмісти C використовують директиву препроцесора під назвою #include, щоб вставити вміст одного файлу в інший під час компіляції. Оператор Ruby include просто посилається на модуль. Якщо цей модуль перебуває в окремому файлі, для використання цього файлу потрібно використовувати (або його рідше використовуваний двоюрідний брат, завантажувати), перш ніж використовувати include. По-друге, включення Ruby не просто копіює методи екземпляра модуля в клас. Натомість він робить посилання з класу на включений модуль. Якщо цей модуль включає кілька класів, всі вони вказують на одне і те ж. Якщо ви зміните визначення методу в модулі, навіть коли ваша програма працює,


3

Коли ви включаєте модуль у свій клас, як показано нижче, це так, як якщо б ви взяли код, визначений в модулі, і вставили його в клас, куди ви його "включили". Це дозволяє поведінку "mixin". Використовується для висушування вашого коду, щоб уникнути дублювання, наприклад, якщо в модулі було декілька класів, яким потрібен би той самий код.

Навантаження Метод завантаження майже як метод вимагає, за винятком того, що він не відслідковує, завантажена чи ні бібліотека. Таким чином, можна завантажувати бібліотеку кілька разів, а також, використовуючи метод завантаження, ви повинні вказати розширення ".rb" імені файлу бібліотеки.

Вимагати Метод вимагає завантаження бібліотеки та запобігає завантаженню не раз. Метод вимагає повернути "false", якщо ви спробуєте завантажити ту саму бібліотеку після першого разу. Метод вимагає використовувати лише в тому випадку, якщо бібліотека, яку ви завантажуєте, визначена в окремому файлі, як правило.

Ви можете віддати перевагу цьому http://ionrails.com/2009/09/19/ruby_require-vs-load-vs-include-vs-extend/


3

Нижче наведено кілька основних відмінностей між потребою та включайте:

Потрібно:

  1. Потрібно читає файл з файлової системи, аналізує його, зберігає в пам'яті і запускає його в заданому місці, що означає, якщо ви навіть щось зміните під час запуску сценарію, ніж ця зміна не відображатиметься.
  2. Нам потрібен файл по імені, а не по імені модуля.
  3. Зазвичай використовується для бібліотек та розширень.

Включати:

  1. Коли ви включаєте модуль у свій клас, він поводиться так, ніби ви взяли код, визначений у вашому модулі, і вставили його у свій клас.
  2. Ми включаємо ім'я модуля, а не ім'я файлу.
  3. Зазвичай використовується для висушування коду та видалення дублювання коду.

2
require(name)

Він поверне bolean істинним / хибним

Ім'я, яке передається як параметр до вимоги, ruby ​​спробує знайти вихідний файл з цим ім'ям у вашому шляху завантаження. Метод вимагає повернути "false", якщо ви спробуєте завантажити ту саму бібліотеку після першого разу. Метод вимагає використовувати лише тоді, коли бібліотека, яку ви завантажуєте, визначена в окремому файлі. Отже, він відслідковує, завантажена ця бібліотека чи ні.

include module_name

Припустимо, якщо у вас є кілька методів, які вам потрібно мати у двох різних класах. Тоді не потрібно писати їх у обидва класи. Замість того, що ви можете зробити, визначте це в модулі. А потім включіть цей модуль в інші класи. Він надається Ruby тільки для забезпечення принципу DRY. Він використовується для висушування коду, щоб уникнути дублювання


2

Включати

Коли ви includeмодуль входите до свого класу, це як би ви взяли визначений в модулі код і вставили його в клас, куди ви його "включили". Це дозволяє поведінку "mixin". Використовується для висушування вашого коду, щоб уникнути дублювання, наприклад, якщо в модулі було декілька класів, яким потрібен би той самий код.

module Log 
  def class_type
    "This class is of type: #{self.class}"
  end
end

class TestClass 
  include Log 
  # ... 
end

tc = TestClass.new.class_type # -> success
tc = TestClass.class_type # -> error

Вимагають

Метод вимагає дозволяє завантажити бібліотеку і запобігає її завантаженню не один раз. Метод вимагає повернути "false", якщо ви спробуєте завантажити ту саму бібліотеку після першого разу. Метод вимагає використовувати лише в тому випадку, якщо бібліотека, яку ви завантажуєте, визначена в окремому файлі, як правило.

Отже, він відслідковує, завантажена ця бібліотека чи ні. Також не потрібно вказувати розширення ".rb" імені файлу бібліотеки. Ось приклад того, як використовувати потрібно. Розташуйте потрібний метод у верхній частині файлу ".rb":

Навантаження

Метод завантаження майже як метод вимагає, за винятком того, що він не відстежує, завантажена чи ні ця бібліотека. Таким чином, можна завантажувати бібліотеку кілька разів, а також, використовуючи метод завантаження, ви повинні вказати розширення ".rb" імені файлу бібліотеки.

Розширити

Використовуючи метод розширення замість включати, ви додаєте методи модуля як методи класу, а не як методи екземпляра.

module Log 
  def class_type
    "This class is of type: #{self.class}"
  end
end

class TestClass 
  extend Log 
  # ... 
end

tc = TestClass.class_type

2

"Завантажити" - вставляє вміст файлу. (Розбирає файл щоразу, коли файл викликається)

'Потрібно' - вставляє вміст, проаналізований у файлі. (Файл розбирається один раз і зберігається в пам'яті)

'Включити' - включає модуль у клас і може використовувати методи всередині модуля як метод екземпляра класу

'Extend' - включає модуль у клас і може використовувати методи всередині модуля як метод класу

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