Perbedaan antara kelas dan modul


438

Saya berasal dari Jawa, dan sekarang saya lebih banyak bekerja dengan Ruby.

Salah satu fitur bahasa yang saya tidak kenal adalah module. Saya bertanya-tanya apa sebenarnya itu moduledan kapan Anda menggunakannya, dan mengapa menggunakan modulelebih dari satu class?


Jawaban:


398

Jawaban pertama adalah baik dan memberikan beberapa jawaban struktural, tetapi pendekatan lain adalah memikirkan apa yang Anda lakukan. Modul adalah tentang memberikan metode yang dapat Anda gunakan di beberapa kelas - pikirkan tentang mereka sebagai "perpustakaan" (seperti yang akan Anda lihat di aplikasi Rails). Kelas adalah tentang objek; modul tentang fungsi.

Misalnya, sistem otentikasi dan otorisasi adalah contoh modul yang baik. Sistem otentikasi bekerja di beberapa kelas level aplikasi (pengguna diautentikasi, sesi mengelola otentikasi, banyak kelas lain akan bertindak secara berbeda berdasarkan status autentikasi), sehingga sistem otentikasi bertindak sebagai API bersama.

Anda mungkin juga menggunakan modul ketika Anda telah berbagi metode di beberapa aplikasi (sekali lagi, model perpustakaan baik di sini).


7
Apakah modul sama dengan Antarmuka di java?
Saad Rehman Shah

14
@ Kafein sebenarnya bukan karena modul Ruby sebenarnya menyertakan implementasi, sedangkan antarmuka di Jawa abstrak
Jorge Israel Peña

8
Tidak, Modul dan Paket Java / JAR adalah binatang yang sama sekali berbeda.
Karoly Horvath

9
Saya lebih suka kelas abstrak dengan implementasi metode.
Otomatis

2
Sebenarnya, @Chole menemukan salah satu hal menarik tentang modul: Namespacing. Jadi, sementara Modul tidak setara langsung dengan paket di Jawa, itu dapat digunakan untuk mencapai sesuatu yang serupa: blog.rubybestpractices.com/posts/gregory/…
michaelok

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)          ║
╚═══════════════╩═══════════════════════════╩═════════════════════════════════╝

Apa superclass dari kelas 'Kelas'?
Aashish P

10
Saya mendapat hierarki, Kelas -> Modul -> Objek -> BasicObject. Keren!!
Aashish P

Mengapa "modul terdiri dari" menghilangkan variabel, ketika kelas dan modul keduanya mendukung variabel kelas? Lihat jawaban yang diterima untuk stackoverflow.com/questions/5690458/…
kaleidic

Banyak diagram dalam semua jawaban ini. Contoh kecil: rubyfiddle.com/riddles/06081
Donato

16
Bagaimana sebuah modul "tidak dapat dipakai" dan belum memiliki metode contoh?
devius

91

Saya terkejut ada yang belum mengatakan ini.

Karena penanya berasal dari latar belakang Jawa (dan saya juga), inilah analogi yang membantu.

Kelas hanya seperti kelas Java.

Modul seperti kelas statis Java. Pikirkan tentang Mathkelas di Jawa. Anda tidak instantiate, dan Anda menggunakan kembali metode di kelas statis (mis. Math.random()).


11
Tetapi modul juga dapat menambahkan metode instance ke kelas yang disertakan, sementara kelas statis di Java tidak bisa.
Pasang kembali Monica - notmaynard

4
Pernyataan ini juga benar berasal dari latar belakang C # yang berat.
Damon Drake

5
Ini tidak sepenuhnya benar; Modul tidak memiliki metode statis, mereka hanya memiliki metode. Modul dapat "memperpanjang sendiri" (sintaks sebenarnya extend self), membuat metode mereka tersedia untuk selfmetaclass mereka. Ini memungkinkan untuk mengirim metode seperti random()pada Mathmodul. Tetapi pada dasarnya, metode modul tidak dapat dipanggil sendiri self. Ini berkaitan dengan gagasan Ruby tentang selfmetaclasses-nya, dan cara kerja metode pencarian. Lihat "Metaprogramming Ruby" - Paolo Perlotta untuk detailnya.
scottburton11

Saya akan mengatakan modul lebih mirip dengan antarmuka dengan metode di dalamnya (antarmuka Java 8 dengan impl standar) tetapi tidak dapat mewarisi satu dari yang lain tidak seperti antarmuka java
divideByZero

Bagaimana jawaban ini memiliki begitu banyak suara? btw yang dikatakan dalam kata-kata yang lebih baik 1mo sebelumnya: stackoverflow.com/a/17027346/986862
Andre Figueiredo

39

Pada dasarnya, modul tidak dapat digunakan. Ketika kelas menyertakan modul, superclass proksi dihasilkan yang menyediakan akses ke semua metode modul serta metode kelas.

Modul dapat dimasukkan oleh beberapa kelas. Modul tidak dapat diwarisi, tetapi model "mixin" ini menyediakan jenis "pewarisan berganda" yang bermanfaat. OO purists akan tidak setuju dengan pernyataan itu, tetapi jangan biarkan kemurnian menghalangi pekerjaan.


(Jawaban ini awalnya ditautkan http://www.rubycentral.com/pickaxe/classes.html, tetapi tautan itu dan domainnya tidak lagi aktif.)


Yap, ini cara kerjanya. Dengan demikian, modul tidak dapat dibandingkan dengan kelas "statis" Java; superclass proxy (beberapa menyebutnya sebuah "metaclass") menjadi penerima pesan metode pengiriman modul, yang membuat itu lebih sebanding dengan kelas statis di Jawa, dan metode yang bekerja seperti metode statis. Namun, hal yang sama berlaku untuk kelas Ruby, yang dapat menggunakan metode "statis" dengan extendmenggunakan kelas. Ruby sebenarnya tidak membedakan antara metode "instance" dan "class / static" sama sekali, hanya penerimanya saja.
scottburton11

7

Moduledi Ruby, pada tingkat tertentu, sesuai dengan kelas abstrak Java - memiliki metode instance, kelas dapat mewarisi darinya (via include, orang-orang Ruby menyebutnya "mixin"), tetapi tidak memiliki instance. Ada perbedaan kecil lainnya, tetapi informasi sebanyak ini cukup untuk Anda mulai.


6

namespace: modules adalah namespaces ... yang tidak ada di java;)

Saya juga beralih dari Java dan python ke Ruby, saya ingat punya pertanyaan yang persis sama ...

Jadi jawaban yang paling sederhana adalah modul itu adalah namespace, yang tidak ada di Java. Di java, pola pikir terdekat ke namespace adalah sebuah paket .

Jadi modul di ruby ​​seperti apa di java:
class? Tidak ada
antarmuka? Tidak ada
kelas abstrak? Tidak ada
paket? Ya mungkin)

metode statis di dalam kelas di java: sama seperti metode di dalam modul di ruby

Dalam java, unit minimum adalah kelas, Anda tidak dapat memiliki fungsi di luar kelas. Namun dalam ruby ​​ini mungkin (seperti python).

Jadi apa yang masuk ke modul?
kelas, metode, konstanta. Modul melindungi mereka di bawah namespace itu.

Tidak ada contoh: modul tidak dapat digunakan untuk membuat instance

Mixed ins: kadang model inheritance tidak baik untuk kelas, tetapi dalam hal fungsionalitas ingin mengelompokkan satu set kelas / metode / konstanta bersama-sama

Aturan tentang modul dalam ruby:
- Nama modul adalah UpperCamelCase
- konstanta dalam modul adalah SEMUA CAPS (aturan ini sama untuk semua konstanta ruby, tidak spesifik untuk modul)
- metode akses: gunakan. operator
- konstanta akses: gunakan :: simbol

contoh sederhana dari sebuah modul:

module MySampleModule
  CONST1 = "some constant"

  def self.method_one(arg1)
    arg1 + 2
  end
end

cara menggunakan metode di dalam modul:

puts MySampleModule.method_one(1) # prints: 3

cara menggunakan konstanta modul:

puts MySampleModule::CONST1 # prints: some constant

Beberapa konvensi lain tentang modul:
Gunakan satu modul dalam file (seperti kelas ruby, satu kelas per file ruby)


“- metode akses: gunakan. operator - konstanta akses: gunakan :: simbol ”hanya jawaban ini yang menyebutkan ini!
Qiulang

4

Intinya: Modul adalah persilangan antara kelas statis / utilitas dan mixin.

Mixin adalah bagian implementasi "parsial" yang dapat digunakan kembali, yang dapat digabungkan (atau disusun) dengan cara mix & match, untuk membantu menulis kelas baru. Kelas-kelas ini juga dapat memiliki status dan / atau kode sendiri.


1

Kelas

Saat Anda mendefinisikan kelas, Anda menentukan cetak biru untuk tipe data. class hold data, memiliki metode yang berinteraksi dengan data itu dan digunakan untuk instantiate objek.

Modul

  • Modul adalah cara pengelompokan bersama metode, kelas, dan konstanta.

  • Modul memberi Anda dua manfaat utama:

    => Modul menyediakan namespace dan mencegah bentrokan nama. Namespace membantu menghindari konflik dengan fungsi dan kelas dengan nama yang sama yang telah ditulis oleh orang lain.

    => Modul menerapkan fasilitas mixin.

(termasuk Modul di Klazz memberikan contoh akses Klazz ke metode Modul.)

(perpanjang Klazz dengan Mod memberikan kelas Klazz akses ke metode Mods.)


0

Pertama, beberapa kesamaan yang belum disebutkan. Ruby mendukung kelas terbuka, tetapi modul juga terbuka. Bagaimanapun, Kelas mewarisi dari Modul dalam rantai warisan Kelas dan sehingga Kelas dan Modul memiliki beberapa perilaku serupa.

Tetapi Anda perlu bertanya pada diri sendiri apa tujuan memiliki Kelas dan Modul dalam bahasa pemrograman? Kelas dimaksudkan untuk menjadi cetak biru untuk membuat instance, dan setiap instance adalah variasi realisasi cetak biru. Sebuah instance hanyalah variasi yang disadari dari cetak biru (Kelas). Tentu saja, Kelas berfungsi sebagai objek penciptaan. Selain itu, karena kami terkadang ingin satu cetak biru berasal dari cetak biru lain, Kelas dirancang untuk mendukung warisan.

Modul tidak dapat dipakai, tidak membuat objek, dan tidak mendukung warisan. Jadi ingat satu modul TIDAK mewarisi dari yang lain!

Jadi apa gunanya memiliki Modul dalam bahasa? Salah satu penggunaan Modul yang jelas adalah untuk membuat namespace, dan Anda akan melihat ini dengan bahasa lain juga. Sekali lagi, apa yang keren tentang Ruby adalah Modul dapat dibuka kembali (seperti halnya Kelas). Dan ini adalah penggunaan besar ketika Anda ingin menggunakan kembali namespace dalam file Ruby yang berbeda:

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

Tetapi tidak ada warisan antar modul:

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>

Modul Apple tidak mewarisi metode apa pun dari modul Hijau dan ketika kami memasukkan Apple dalam kelas Buah, metode modul Apple ditambahkan ke rantai leluhur instans Apple, tetapi bukan metode modul Green, meskipun Green Modul didefinisikan dalam modul Apple.

Jadi bagaimana kita mendapatkan akses ke metode hijau? Anda harus secara eksplisit memasukkannya ke dalam kelas Anda:

class Fruit
  include Apple::Green
end
 => Fruit 
 > f.green
=> green

Tetapi Ruby memiliki penggunaan penting lainnya untuk Modul. Ini adalah fasilitas Mixin, yang saya jelaskan dalam jawaban lain pada SO. Tetapi untuk meringkas, mixin memungkinkan Anda untuk mendefinisikan metode ke dalam rantai objek warisan. Melalui mixin, Anda bisa menambahkan metode ke rantai turunan instance objek (termasuk) atau singleton_class of self (extended).

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.