Java'dan geldim ve şimdi Ruby ile daha çok çalışıyorum.
Aşina olmadığım bir dil özelliği module
. Tam olarak ne olduğunu module
ve ne zaman kullandığınızı merak ediyorum ve neden bir module
over a kullanıyorsunuz class
?
Java'dan geldim ve şimdi Ruby ile daha çok çalışıyorum.
Aşina olmadığım bir dil özelliği module
. Tam olarak ne olduğunu module
ve ne zaman kullandığınızı merak ediyorum ve neden bir module
over a kullanıyorsunuz class
?
Yanıtlar:
İlk cevap iyidir ve bazı yapısal cevaplar verir, ancak başka bir yaklaşım ne yaptığınızı düşünmektir. Modüller, birden fazla sınıfta kullanabileceğiniz yöntemler sağlamakla ilgilidir - bunları "kitaplıklar" olarak düşünün (bir Rails uygulamasında gördüğünüz gibi). Sınıflar nesnelerle ilgilidir; modüller işlevlerle ilgilidir.
Örneğin, kimlik doğrulama ve yetkilendirme sistemleri modüllerin iyi örnekleridir. Kimlik doğrulama sistemleri birden çok uygulama düzeyinde sınıfta çalışır (kullanıcılar kimlik doğrulanır, oturumlar kimlik doğrulamayı yönetir, diğer birçok sınıf kimlik doğrulama durumuna göre farklı şekilde çalışır), bu nedenle kimlik doğrulama sistemleri paylaşılan API'lar olarak işlev görür.
Birden fazla uygulamada yöntemleri paylaştığınızda bir modül de kullanabilirsiniz (yine, kütüphane modeli burada iyidir).
╔═══════════════╦═══════════════════════════╦═════════════════════════════════╗
║ ║ 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) ║
╚═══════════════╩═══════════════════════════╩═════════════════════════════════╝
Kimsenin bunu henüz söylemediğine şaşırdım.
Asker bir Java geçmişinden geldiğinden (ve ben de), işte size yardımcı olan bir benzetme.
Sınıflar sadece Java sınıfları gibidir.
Modüller Java statik sınıflarına benzer. Math
Java sınıfını düşünün . Bunu somutlaştırmazsınız ve statik sınıftaki yöntemleri yeniden kullanırsınız (örn. Math.random()
).
extend self
), yöntemlerini kendi self
metasınıfları için kullanılabilir hale getirir . Bu random()
, bir Math
modülde olduğu gibi bir yöntem göndermeyi mümkün kılar . Ancak doğası gereği, bir modülün yöntemleri modülün kendi başına çağrılamaz self
. Bu, Ruby'nin self
metasınıfları ve yöntem arama yönteminin nasıl çalıştığı ile ilgilidir. Ayrıntılar için "Metaprogramming Ruby" - Paolo Perlotta'ya göz atın.
Temel olarak, modül somutlaştırılamaz. Bir sınıf bir modül içerdiğinde, tüm modül yöntemlerine ve sınıf yöntemlerine erişim sağlayan bir proxy üst sınıfı oluşturulur.
Bir modül birden fazla sınıf tarafından eklenebilir. Modüller kalıtsal olamaz, ancak bu "mixin" modeli faydalı bir "çoklu kalıtım" tipi sağlar. OO puristleri bu ifadeye katılmayacaklar, ancak saflığın işin yapılmasını engellemesine izin vermeyin.
(Bu yanıt başlangıçta bağlandı http://www.rubycentral.com/pickaxe/classes.html
, ancak bu bağlantı ve etki alanı artık etkin değil.)
extend
bir sınıf oluşturarak "statik" benzeri yöntemler alabilir . Ruby aslında "örnek" ve "sınıf / statik" yöntemleri birbirinden ayırmaz, yalnızca alıcılarını ayırır.
Module
Ruby'de, bir dereceye kadar, Java soyut sınıfına karşılık gelir - örnek yöntemleri vardır, sınıflar ondan miras alabilir (aracılığıyla include
, Ruby çocuklar bunu "mixin" olarak adlandırır), ancak örnekleri yoktur. Başka küçük farklılıklar da var, ancak bu kadar bilgi başlamanız için yeterli.
namespace: modüller java'da olmayan ad alanlarıdır ;)
Ayrıca Java ve python'dan Ruby'ye geçtim, aynı soruya sahip olduğumu hatırlıyorum ...
Bu yüzden en basit cevap, modülün Java'da bulunmayan bir ad alanı olmasıdır. Java'da ad alanına en yakın zihniyet bir pakettir .
Yani yakuttaki bir modül java:
class'taki gibi mi?
Arayüz yok mu?
Soyut sınıf yok mu?
Paket yok mu? Evet belki)
Java'daki sınıflar içindeki statik yöntemler: Ruby'deki modüllerin içindeki yöntemlerle aynı
Java'da minimum birim bir sınıftır, sınıf dışında bir işleve sahip olamazsınız. Ancak yakutta bu mümkündür (python gibi).
Peki bir modüle ne giriyor?
sınıflar, yöntemler, sabitler. Modül onları bu ad alanı altında korur.
Örnek yok: modüller örnek oluşturmak için kullanılamaz
Karışık ins: bazen miras modelleri sınıflar için iyi değildir, ancak işlevsellik açısından bir grup sınıfı / yöntemi / sabiti birlikte gruplandırmak ister
Ruby'deki modüller hakkında kurallar: - Modül adları UpperCamelCase'dir
- modüller içindeki sabitler TÜM CAPS'tır (bu kural modüllere özgü olmayan tüm ruby sabitleri için aynıdır)
- erişim yöntemleri: kullanım. Şebeke
- erişim sabitleri: use :: symbol
basit bir modül örneği:
module MySampleModule
CONST1 = "some constant"
def self.method_one(arg1)
arg1 + 2
end
end
bir modül içindeki yöntemlerin nasıl kullanılacağı:
puts MySampleModule.method_one(1) # prints: 3
bir modülün sabitleri nasıl kullanılır:
puts MySampleModule::CONST1 # prints: some constant
Modüller hakkında diğer bazı kurallar:
Dosyada bir modül kullanın (ruby sınıfları, ruby dosyası başına bir sınıf gibi)
Alt satır: Bir modül, statik / hizmet sınıfı ve mixin arasındaki çaprazlamadır.
Mixins, yeni sınıfların yazılmasına yardımcı olmak için mix & match tarzında birleştirilebilen (veya oluşturulabilen) yeniden kullanılabilir "kısmi" uygulama parçalarıdır. Bu sınıfların ek olarak kendi durumları ve / veya kodları da olabilir.
Sınıf
Sınıf tanımladığınızda, veri türü için bir plan tanımlarsınız. sınıf tutma verileri, bu verilerle etkileşimde bulunan ve nesneleri somutlaştırmak için kullanılan yöntemlere sahiptir.
modül
Modüller yöntemleri, sınıfları ve sabitleri bir arada gruplamanın bir yoludur.
Modüller size iki önemli avantaj sağlar:
=> Modüller bir ad alanı sağlar ve ad çakışmalarını önler. Ad alanı, başkası tarafından yazılmış aynı ada sahip işlevler ve sınıflarla çakışmaları önlemeye yardımcı olur.
=> Modüller mixin tesisini uygular.
(Klazz'daki Modül dahil, Klazz'ın Modül yöntemlerine erişimini sağlar.)
(Klazz'ı Mod ile genişleterek sınıfın Klazz'a Mods yöntemlerine erişmesini sağlayın.)
İlk olarak, henüz bahsedilmeyen bazı benzerlikler. Ruby açık sınıfları destekler, ancak modüller de açıktır. Sonuçta, Class, Class miras zincirindeki Modül'den miras alır ve böylece Class ve Module benzer davranışlara sahiptir.
Ancak kendinize, bir programlama dilinde bir Sınıf ve bir Modüle sahip olmanın amacının ne olduğunu sormanız gerekir? Bir sınıf, örneklerin oluşturulması için bir plan olarak tasarlanmıştır ve her örnek, planın gerçekleştirilmiş bir varyasyonudur. Bir örnek sadece bir planın (Sınıf) farkına varılmış bir varyasyonudur. Doğal olarak, Sınıflar nesne oluşturma işlevi görür. Dahası, bazen bir planın başka bir plandan türetilmesini istediğimizden, Sınıflar kalıtımı desteklemek üzere tasarlanmıştır.
Modüller somutlaştırılamaz, nesne oluşturmaz ve kalıtımı desteklemez. Bir modülün diğerinden devralmadığını unutmayın!
Peki bir dilde Modüllere sahip olmanın anlamı nedir? Modüllerin bariz bir kullanımı bir ad alanı oluşturmaktır ve bunu diğer dillerle de fark edeceksiniz. Yine, Ruby ile ilgili güzel olan şey Modüllerin yeniden açılabilir olmasıdır (tıpkı Sınıflar gibi). Farklı Ruby dosyalarında bir ad alanını yeniden kullanmak istediğinizde bu büyük bir kullanımdır:
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
Ancak modüller arasında kalıtım yoktur:
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>
Apple modülü Green modülünden herhangi bir yöntem miras almamıştır ve Apple'ı Fruit sınıfına dahil ettiğimizde Apple modülünün yöntemleri Apple örneklerinin ata zincirine eklenir, ancak Green modülünün yöntemleri Yeşil olmasa bile modülü Apple modülünde tanımlanmıştır.
Peki yeşil yönteme nasıl erişebiliriz? Sınıfınıza açıkça eklemeniz gerekir:
class Fruit
include Apple::Green
end
=> Fruit
> f.green
=> green
Ancak Ruby'nin Modüller için bir başka önemli kullanımı daha var. Bu SO üzerine başka bir cevapta tarif ettiğim Mixin tesisi. Ancak özetlemek gerekirse, karışımlar, nesnelerin miras zincirine yöntemleri tanımlamanıza izin verir. Mixins aracılığıyla, nesne örneklerinin kalıtım zincirine (include) veya self (genişletme) singleton_class yöntemlerine yöntemler ekleyebilirsiniz.