Pochodzę z Javy i teraz pracuję więcej z Ruby.
Jedną z nieznanych mi funkcji językowych jest module. Zastanawiam się, co to dokładnie jest modulei kiedy używasz jednego z nich, a po co używać go modulepowyżej class?
Pochodzę z Javy i teraz pracuję więcej z Ruby.
Jedną z nieznanych mi funkcji językowych jest module. Zastanawiam się, co to dokładnie jest modulei kiedy używasz jednego z nich, a po co używać go modulepowyżej class?
Odpowiedzi:
Pierwsza odpowiedź jest dobra i zawiera odpowiedzi strukturalne, ale innym podejściem jest zastanowienie się nad tym, co robisz. Moduły polegają na udostępnianiu metod, których można używać w wielu klasach - pomyśl o nich jak o „bibliotekach” (jak zobaczysz w aplikacji Rails). Klasy dotyczą przedmiotów; moduły dotyczą funkcji.
Na przykład systemy uwierzytelniania i autoryzacji są dobrymi przykładami modułów. Systemy uwierzytelniania działają w wielu klasach na poziomie aplikacji (użytkownicy są uwierzytelnieni, sesje zarządzają uwierzytelnianiem, wiele innych klas będzie działać inaczej w zależności od stanu uwierzytelnienia), więc systemy uwierzytelniania działają jako wspólne interfejsy API.
Możesz także użyć modułu, jeśli udostępniasz metody w wielu aplikacjach (znowu model biblioteki jest tutaj dobry).
╔═══════════════╦═══════════════════════════╦═════════════════════════════════╗
║ ║ class ║ module ║
╠═══════════════╬═══════════════════════════╬═════════════════════════════════╣
║ instantiation ║ can be instantiated ║ can *not* be instantiated ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ usage ║ object creation ║ mixin facility. provide ║
║ ║ ║ a namespace. ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ superclass ║ module ║ object ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ methods ║ class methods and ║ module methods and ║
║ ║ instance methods ║ instance methods ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ inheritance ║ inherits behaviour and can║ No inheritance ║
║ ║ be base for inheritance ║ ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ inclusion ║ cannot be included ║ can be included in classes and ║
║ ║ ║ modules by using the include ║
║ ║ ║ command (includes all ║
║ ║ ║ instance methods as instance ║
║ ║ ║ methods in a class/module) ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ extension ║ can not extend with ║ module can extend instance by ║
║ ║ extend command ║ using extend command (extends ║
║ ║ (only with inheritance) ║ given instance with singleton ║
║ ║ ║ methods from module) ║
╚═══════════════╩═══════════════════════════╩═════════════════════════════════╝
Dziwię się, że nikt jeszcze tego nie powiedział.
Ponieważ pytający pochodził z języka Java (podobnie jak ja), oto analogia, która pomaga.
Klasy są po prostu jak klasy Java.
Moduły są jak klasy statyczne Java. Pomyśl o Mathklasie w Javie. Nie tworzysz go i ponownie używasz metod w klasie statycznej (np. Math.random()).
extend self), udostępniając swoje metody selfmetaklasie. Umożliwia to wysłanie metody takiej jak random()w Mathmodule. Ale ze względu na swój charakter metody modułu nie mogą być wywoływane samodzielnie self. Ma to związek z pojęciem Ruby self, jej metaklasami i działaniem wyszukiwania metod. Sprawdź „Metaprogramowanie Ruby” - Paolo Perlotta, aby uzyskać szczegółowe informacje.
Zasadniczo nie można utworzyć instancji modułu. Gdy klasa zawiera moduł, generowana jest nadklasa proxy, która zapewnia dostęp do wszystkich metod modułowych, a także metod klasowych.
Moduł może być zawarty w wielu klasach. Moduły nie mogą być dziedziczone, ale ten model „mixin” zapewnia użyteczny typ „wielokrotnego dziedziczenia”. OO, puryści, nie zgodzą się z tym stwierdzeniem, ale nie pozwólcie, aby czystość przeszkodziła w wykonaniu zadania.
(Ta odpowiedź była pierwotnie połączona z http://www.rubycentral.com/pickaxe/classes.htmltym linkiem, ale ten link i jego domena nie są już aktywne).
extendwejście do klasy. Ruby tak naprawdę w ogóle nie rozróżnia metod „instancja” i „klasa / statyczny”, tylko ich odbiorniki.
Modulew Ruby, do pewnego stopnia, odpowiada klasie abstrakcyjnej Java - ma metody instancji, klasy mogą dziedziczyć po niej (przez include, chłopaki Ruby nazywają to „mixinem”), ale nie ma instancji. Istnieją inne drobne różnice, ale tyle informacji wystarczy, aby zacząć.
przestrzeń nazw: moduły to przestrzenie nazw ... które nie istnieją w java;)
Zmieniłem też język Java i Python na Ruby, pamiętam, że miałem dokładnie to samo pytanie ...
Najprostszą odpowiedzią jest to, że moduł jest przestrzenią nazw, która nie istnieje w Javie. W Javie najbardziej zbliżonym do przestrzeni nazw jest pakiet .
Tak więc moduł w Rubim jest podobny do java:
class? Brak
interfejsu? Brak
klasy abstrakcyjnej? Brak
paczki? Tak, może)
metody statyczne wewnątrz klas w Javie: takie same jak metody wewnątrz modułów w Rubim
W Javie minimalną jednostką jest klasa, nie można mieć funkcji poza klasą. Jednak w Rubim jest to możliwe (jak Python).
Co wchodzi w moduł?
klasy, metody, stałe. Moduł chroni je pod tą przestrzenią nazw.
Brak instancji: modułów nie można używać do tworzenia instancji
Mieszane elementy: czasami modele dziedziczenia nie są dobre dla klas, ale pod względem funkcjonalności chcą zgrupować zestaw klas / metod / stałych razem
Reguły dotyczące modułów w Rubim:
- Nazwy modułów to UpperCamelCase
- stałe w modułach to WSZYSTKIE KAPSYKI (ta reguła jest taka sama dla wszystkich stałych ruby, nie dotyczy modułów)
- metody dostępu: użyj. operator
- stałe dostępu: użyj :: symbol
prosty przykład modułu:
module MySampleModule
CONST1 = "some constant"
def self.method_one(arg1)
arg1 + 2
end
end
jak korzystać z metod wewnątrz modułu:
puts MySampleModule.method_one(1) # prints: 3
jak używać stałych modułu:
puts MySampleModule::CONST1 # prints: some constant
Inne konwencje dotyczące modułów:
Użyj jednego modułu w pliku (np. Klasy ruby, jedna klasa na plik ruby)
Konkluzja: Moduł jest skrzyżowaniem klasy statycznej / użytecznej z mixinem.
Mixiny to fragmenty „częściowej” implementacji wielokrotnego użytku, które można łączyć (lub komponować) w sposób mix & match, aby pomóc pisać nowe klasy. Klasy te mogą dodatkowo mieć swój własny stan i / lub kod.
Klasa
Podczas definiowania klasy definiuje się plan dla typu danych. klasy przechowują dane, mają metodę, która wchodzi w interakcję z tymi danymi i są używane do tworzenia instancji obiektów.
Moduł
Moduły to sposób grupowania metod, klas i stałych.
Moduły dają dwie główne korzyści:
=> Moduły zapewniają przestrzeń nazw i zapobiegają konfliktom nazw. Przestrzeń nazw pomaga uniknąć konfliktów z funkcjami i klasami o tej samej nazwie, które zostały napisane przez kogoś innego.
=> Moduły implementują funkcję mixin.
(w tym moduł w Klazz daje instancjom dostęp do metod modułu.)
(rozszerz Klazza o Mod, dając klasie Klazz dostęp do metod Modów.)
Po pierwsze, pewne podobieństwa, o których jeszcze nie wspomniano. Ruby obsługuje otwarte klasy, ale moduły również są otwarte. W końcu klasa dziedziczy po module w łańcuchu dziedziczenia klas, a zatem klasa i moduł mają podobne zachowanie.
Ale musisz zadać sobie pytanie, jaki jest cel posiadania zarówno klasy, jak i modułu w języku programowania? Klasa ma być planem tworzenia instancji, a każda instancja jest zrealizowaną odmianą projektu. Instancja jest tylko zrealizowaną odmianą planu (Klasa). Oczywiście wtedy Klasy działają jak tworzenie obiektów. Ponadto, ponieważ czasami chcemy, aby jeden plan wywodził się z innego, Klasy mają na celu wspieranie dziedziczenia.
Nie można tworzyć instancji modułów, nie tworzyć obiektów i nie obsługiwać dziedziczenia. Pamiętaj więc, że jeden moduł NIE dziedziczy po innym!
Jaki jest więc sens posiadania modułów w języku? Jednym z oczywistych zastosowań modułów jest utworzenie przestrzeni nazw, a zauważysz to również w innych językach. Znów fajne w Ruby jest to, że można ponownie otworzyć moduły (podobnie jak klasy). Jest to duże zastosowanie, gdy chcesz ponownie użyć przestrzeni nazw w różnych plikach Ruby:
module Apple
def a
puts 'a'
end
end
module Apple
def b
puts 'b'
end
end
class Fruit
include Apple
end
> f = Fruit.new
=> #<Fruit:0x007fe90c527c98>
> f.a
=> a
> f.b
=> b
Ale nie ma dziedziczenia między modułami:
module Apple
module Green
def green
puts 'green'
end
end
end
class Fruit
include Apple
end
> f = Fruit.new
=> #<Fruit:0x007fe90c462420>
> f.green
NoMethodError: undefined method `green' for #<Fruit:0x007fe90c462420>
Moduł Apple nie odziedziczył żadnych metod z modułu Green, a kiedy umieściliśmy Apple w klasie Fruit, metody modułu Apple są dodawane do łańcucha przodków instancji Apple, ale nie metody z modułu Green, nawet jeśli Green moduł został zdefiniowany w module Apple.
Jak więc uzyskać dostęp do zielonej metody? Musisz wyraźnie dołączyć to do swojej klasy:
class Fruit
include Apple::Green
end
=> Fruit
> f.green
=> green
Ale Ruby ma inne ważne zastosowanie dla modułów. To jest funkcja Mixin, którą opisuję w innej odpowiedzi na SO. Podsumowując, mixiny pozwalają definiować metody w łańcuchu dziedziczenia obiektów. Za pomocą mixin można dodawać metody do łańcucha dziedziczenia instancji obiektów (dołącz) lub singleton_class self (przedłużyć).