Sınıf ve modül arasındaki fark


438

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 moduleve ne zaman kullandığınızı merak ediyorum ve neden bir moduleover a kullanıyorsunuz class?


Yanıtlar:


398

İ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).


7
Modül Java'daki arayüzlerle aynı mı?
Saad Rehman Shah

14
@Cffeffeine, Ruby modülleri aslında uygulamaları içerdiğinden değil, Java'daki arayüzler soyut
Jorge İsrail Peña

8
Hayır, Modüller ve Java Paketleri / JAR'ları tamamen farklı hayvanlardır.
Karoly Horvath

9
Daha çok yöntem uygulaması olan soyut sınıflara benziyorum.
Automatico

2
Aslında, @Chole modüllerle ilgili güzel şeylerden birine çarpar: İsimlendirme. Dolayısıyla, Modüller Java'daki paketlere doğrudan eşdeğer olmasa da, benzer bir şey elde etmek için kullanılabilir: blog.rubybestpractices.com/posts/gregory/…
michaelok 15:15

513
╔═══════════════╦═══════════════════════════╦═════════════════════════════════╗
║               ║ 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)          ║
╚═══════════════╩═══════════════════════════╩═════════════════════════════════╝

'Sınıf' sınıfının üst sınıfı nedir?
Aashish P

10
Sınıf -> Modül -> Nesne -> BasicObject hiyerarşisini aldım. Güzel!!
Aashish P

Sınıflar ve modüller sınıf değişkenlerini desteklediğinde, "modül" neden atlanır değişkenlerden oluşur? Kabul cevabı için bkz stackoverflow.com/questions/5690458/...
kaleidic

Tüm bu cevaplarda bir sürü diyagram var. Küçük bir örnek: rubyfiddle.com/riddles/06081
Donato

16
Bir modül nasıl "somutlaştırılamaz" ve yine de örnek yöntemlere sahip olabilir?
devius

91

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. MathJava 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()).


11
Ancak modüller, include sınıfına örnek yöntemleri eklerken Java'daki statik sınıflar da ekleyemez.
Monica'yı eski durumuna getirme - notmaynard

4
Bu ifade, ağır bir C # arka planından gelenler için de geçerlidir.
Damon Drake

5
Bu tamamen doğru değil; modüllerin statik yöntemleri yoktur, sadece yöntemleri vardır. Modüller "kendilerini genişletebilir" (sözdizimi aslında extend self), yöntemlerini kendi selfmetasınıfları için kullanılabilir hale getirir . Bu random(), bir Mathmodü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 selfmetası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.
scottburton11

Modüllerin bunlardaki yöntemlerle (varsayılan impl ile Java 8 arabirimleri) daha benzer olduğunu söyleyebilirim, ancak java arabirimlerinin aksine diğerinden miras
alamazsınız

Bu cevabın kaç oyu var? btw daha iyi kelimeler 1mo önce söyledi: stackoverflow.com/a/17027346/986862
Andre Figueiredo

39

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.)


Evet, işte böyle çalışıyor. Bunun gibi, modüller şunlardır değil Java'nın "statik" sınıfları ile karşılaştırılabilir; Proxy üst sınıf (bazı çağrı it bir "metaclass") yapar modülün yöntem sevk mesajlarının alıcı, olur o Java statik sınıfına daha karşılaştırılabilir ve bunun yöntemleri statik yöntemlere gibi çalışırlar. Ancak aynı durum, Ruby'nin sınıfları için de geçerlidir ve bu da extendbir 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.
scottburton11

7

ModuleRuby'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.


6

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)


“- erişim yöntemleri: kullanın. operatör - erişim sabitleri: use :: symbol ”sadece bu cevap bundan bahsetti!
Qiulang

4

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.


1

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.)


0

İ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.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.