Koja je razlika između uključivanja i proširenja u Ruby?

Samo gledam Rubyjev metaprogram. Mixin / moduli uvijek me zbunjuju.

  • uključuju : miješa u navedenim modularnim metodama kao metode instance u ciljnoj klasi
  • expand : miješa u specificiranim modularnim metodama kao metode klasa u ciljnoj klasi

Dakle, je li glavna razlika između ovog ili većeg skrivanja zmaja? na primjer.

 module ReusableModule def module_method puts "Module Method: Hi there!" end end class ClassThatIncludes include ReusableModule end class ClassThatExtends extend ReusableModule end puts "Include" ClassThatIncludes.new.module_method # "Module Method: Hi there!" puts "Extend" ClassThatExtends.module_method # "Module Method: Hi there!" 
333
01 окт. postavila Gishu na Oct 01 2008-10-01 08:40 '08 u 8:40 2008-10-01 08:40
@ 6 odgovora

Ono što ste rekli je istina. Međutim, ima još toga.

Ako imate Klazz klasu i modul Mod , uključujući Mod u Klazz , pruža primjere Klazz pristupa Mod metodama. Ili možete proširiti Klazz s Klazz , dajući Klazz klasi pristup Mod metodama. No, također možete proširiti proizvoljni objekt koristeći o.extend Mod . U ovom slučaju, odvojeni objekt prima Mod , iako svi ostali objekti s istom klasom kao o ne.

203
01 окт. odgovor je dangblackwell 01 okt. 2008-10-01 12:59 '08 u 12:59 2008-10-01 12:59

expand - dodaje specificirane metode i konstante modula ciljnom metaklasu (tj. klasi singleta) na primjer

  • ako nazovete Klazz.extend(Mod) , sada Klazz ima Mod metode (kao metode klasa)
  • ako nazovete obj.extend(Mod) , obj sada ima Mod metode (kao metode instance), ali nijedna druga instanca obj.class dodala ove metode.
  • extend je javna metoda.

omogućiti . Prema zadanim postavkama, on se miješa u navedenim modularnim metodama kao metode instance u ciljnom modulu / klasi. na primjer.

  • ako nazovete class Klazz; include Mod; end; class Klazz; include Mod; end; , sada svi Klazz instanci imaju pristup Mod metodama (kao metode instance).
  • include je privatna metoda, budući da je namijenjena za pozivanje iz kontejnera klase / modula.

Međutim , moduli vrlo često nadjačavaju ponašanje ponašanja anesteziranjem included metode. To je vrlo vidljivo u zastarjelom Rails kodu. Detalji iz Yehude Katz .

border=0

Dodatne informacije o include sa zadanim ponašanjem, pod uvjetom da ste izvršili sljedeći kôd

 class Klazz include Mod end 
  • Ako je Mod već uključen u Klazz ili jedan od njegovih predaka, izjava uključivanja nema učinka
  • Ona također uključuje Mod konstante u Klazz, ako se ne sudaraju
  • Klazz daje pristup, primjerice, varijablama modula Mod. @@foo ili @@bar
  • poziva ArgumentError ako postoje ciklički uključci
  • Modul pripisuje kao neposredni predak pozivatelja (tj. Dodaje Mod Klazz.ancestors, ali Mod se ne dodaje u Klazz.superclass.superclass.superclass lanac. Stoga, pozivanje super u Klazz # foo će provjeriti Mod # foo prije provjere super klasa Klazz stvarna klasa Vidi RubySpec za detalje.).

Naravno, dokumentacija rubin kernela je uvijek najbolje mjesto za te stvari. RubySpec projekt je također bio fantastičan izvor, jer su točno prikupili funkcionalnost.

265
15 февр. Odgovor koji je dao John Douthat 15. veljače. 2011-02-15 22:10 '11 u 22:10 2011-02-15 22:10

To je točno.

Iza kulisa, uključi se zapravo pseudonim za append_features , koji (od dokumenata):

Rubyova zadana implementacija je dodavanje konstanti, metoda i varijabli modula ovom modulu u aModule ako ovaj modul još nije dodan u aModule ili jedan od njegovih predaka.

13
01 окт. odgovor dan Toby Hede Oct 01. \ t 2008-10-01 11:08 '08 u 11:08 2008-10-01 11:08

Svi ostali odgovori su dobri, uključujući i savjet za kopanje RubySpecs:

https://github.com/rubyspec/rubyspec/blob/master/core/module/include_spec.rb

https://github.com/rubyspec/rubyspec/blob/master/core/module/extend_object_spec.rb

Što se tiče slučajeva upotrebe:

Ako uključite modul ReusableModule u klasu ClassThatIncludes, reference metoda, konstante, klase, podmodule i druge deklaracije.

Ako proširite klasu ClassThatExtends s modulom ReusableModule, metode i konstante se kopiraju. Očito, ako niste oprezni, možete potrošiti puno memorije dinamički dupliciranje definicije.

Ako koristite ActiveSupport :: Concern, funkcija .included () omogućuje vam izravno ponovno upisivanje uključenog razreda. modul ClassMethods unutar Koncerna je proširen (kopiran) na klasu inkluzije.

4
23 сент. Odgovor dao Ho-Sheng Hsiao 23. rujna 2011-09-23 00:02 '11 u 0:02 2011-09-23 00:02

Također bih želio objasniti mehanizam njegovog funkcioniranja. Ako sam u krivu, ispravite ga.

Kada koristimo include , dodamo link iz naše klase u modul koji sadrži neke metode.

 class A include MyMOd end a = A.new a.some_method 

Objekti nemaju metode, samo klanove i module. Stoga, kada dobiva neku some_method , on pokreće metodu pretraživanja some_method u vlastitoj klasi, a zatim u klasi a , a zatim se povezuje s modulima klase a , ako ih ima (obrnutim redoslijedom, a posljednji uključuje pobjede).

Kada koristimo extend , dodamo link na modul u vlastitoj klasi objekata. Stoga, ako koristimo A.new.extend (MyMod), dodamo vezanje našem modulu u vlastitu klasu instance ili klasu a' . A ako koristimo A.extend (MyMod), dodamo link na A (objekti, klase su također objekti) eigenclass a' .

dakle, put traženja metode za a izgleda ovako: a => a '=> pridruženi moduli s klasom' class => A.

postoji i metoda prepunjavanja koja mijenja put pretraživanja:

a => a '=> dodan modul A => A => je uključen u A

Žao mi je zbog lošeg engleskog.

1
27 марта '16 в 15:11 2016-03-27 15:11 odgovor je dao user1136228 27. ožujka 2011. u 15:11 2016-03-27 15:11

Prije sam to naučila, ali cijenim to kad je koristim. Evo razlike:

To ne radi, ali će raditi ako ga definiram kao def page_views(campaign) :

 class UserAction include Calculations def self.page_views(campaign) overall_profit = calculate_campaign_profit(campaign) end end 

Djeluje:

 class UserAction extend Calculations def self.page_views(campaign) overall_profit = calculate_campaign_profit(campaign) end end 
1
18 апр. odgovor je dao Caner akakmak 18. travnja. 2015-04-18 23:46 '15 u 23:46 2015-04-18 23:46

Ostala pitanja o oznake za ili Postavite pitanje