类和模块之间的区别

时间:2008-09-30 02:11:30

标签: ruby class module

我来自Java,现在我正在使用Ruby。

我不熟悉的一种语言功能是module。我想知道究竟什么是module,你什么时候使用,以及为什么在module上使用class

9 个答案:

答案 0 :(得分:498)

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

答案 1 :(得分:384)

第一个答案是好的并给出了一些结构性答案,但另一种方法是考虑你正在做什么。模块是关于提供可以在多个类中使用的方法 - 将它们视为“库”(正如您在Rails应用程序中看到的那样)。类是关于对象的;模块是关于功能的。

例如,身份验证和授权系统是模块的好例子。身份验证系统跨多个应用程序级别的类(用户进行身份验证,会话管理身份验证,许多其他类将根据身份验证状态采取不同的行为),因此身份验证系统充当共享API。

当你在多个应用程序之间共享方法时,你也可以使用一个模块(同样,这里的库模型很好)。

答案 2 :(得分:85)

我很惊讶有人还没说过这个。

由于提问者来自Java背景(我也是如此),这是一个有用的类比。

类就像Java类一样。

模块就像Java静态类。想想Java中的Math类。您没有实例化它,并且您重用静态类中的方法(例如。Math.random())。

答案 3 :(得分:39)

基本上,模块无法实例化。当一个类包含一个模块时,会生成一个代理超类,它提供对所有模块方法以及类方法的访问。

多个类可以包含一个模块。模块不能被继承,但这种“mixin”模型提供了一种有用的“多重继承”类型。 OO纯粹主义者不同意这种说法,但不要让纯度妨碍完成工作。


(此答案最初与http://www.rubycentral.com/pickaxe/classes.html相关联,但该链接及其域名不再有效。)

答案 4 :(得分:7)

Ruby中的

Module,在某种程度上,对应于Java 抽象类 - 有实例方法,类可以从它继承(通过include,Ruby人称之为一个“mixin”),但没有实例。还有其他一些细微差别,但这些信息足以让您入门。

答案 5 :(得分:5)

命名空间:模块是命名空间 ...在java中不存在;)

我也从Java和python切换到Ruby,我记得有同样的问题......

所以最简单的答案是模块是一个名称空间,在Java中不存在。在java中,最接近命名空间的思维方式是

所以ruby中的模块就像java中的那样:
上课?没有 界面?没有 抽象类?没有 包裹?是(也许)

java中类内部的静态方法:与ruby中模块内部的方法相同

在java中,最小单位是一个类,你不能在类之外有一个函数。但是在ruby中这是可能的(比如python)。

那么进入模块的是什么? 类,方法,常量。模块在该命名空间下保护它们。

无实例:模块不能用于创建实例

混合ins:有时继承模型不适合类,但在功能方面希望将一组类/方法/常量组合在一起

关于ruby中模块的规则:
- 模块名称为UpperCamelCase
- 模块中的常量是ALL CAPS(这个规则对于所有ruby常量都是相同的,不是特定于模块的) - 访问方法:使用。运营商
- 访问常量:use :: symbol

模块的简单示例:

module MySampleModule
  CONST1 = "some constant"

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

如何在模块内使用方法:

puts MySampleModule.method_one(1) # prints: 3

如何使用模块的常量:

puts MySampleModule::CONST1 # prints: some constant

关于模块的其他一些惯例:
在文件中使用一个模块(如ruby类,每个ruby文件一个类)

答案 6 :(得分:4)

底线:模块是静态/实用程序类和mixin之间的交叉。

Mixins是可重复使用的部分"部分"实施,可以在混合和组合中组合(或组合)匹配时尚,帮助写新课程。当然,这些类还可以有自己的状态和/或代码。

答案 7 :(得分:1)

班级

定义类时,可以为数据类型定义蓝图。  class hold data,具有与该数据交互的方法,并用于实例化对象。

<强>模块

  • 模块是一种将方法,类和常量分组在一起的方法。

  • 模块为您带来两大好处:

    =&GT;模块提供命名空间并防止名称冲突。 命名空间有助于避免与其他人编写的具有相同名称的函数和类冲突。

    =&GT;模块实现了mixin工具。

  

(包括Klazz中的Module提供Klazz访问Module的实例   方法。 )

     

(使用Mod扩展Klazz,使Klazz类能够访问Mods方法。)

答案 8 :(得分:0)

首先,一些尚未提及的相似之处。 Ruby支持开放类,但模块也是开放的。毕竟,Class继承自Class继承链中的Module,因此Class和Module确实有类似的行为。

但是你需要问自己,在编程语言中同时使用类和模块的目的是什么?一个类旨在成为创建实例的蓝图,每个实例都是蓝图的实现变体。实例只是蓝图(Class)的实现变体。当然,Classes用作对象创建。此外,由于我们有时希望从另一个蓝图派生出一个蓝图,因此Classes旨在支持继承。

模块无法实例化,不创建对象,也不支持继承。所以请记住,一个模块不会继承另一个模块!

那么在一种语言中使用模块有什么意义呢?模块的一个显而易见的用法是创建命名空间,您也会注意到其他语言。同样,对Ruby来说很酷的是模块可以重新打开(就像Classes一样)。当您想在不同的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

但模块之间没有继承:

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模块没有继承Green模块中的任何方法,当我们将Apple包含在Fruit类中时,Apple模块的方法被添加到Apple实例的祖先链中,但不是Green模块的方法,甚至虽然绿色模块是在Apple模块中定义的。

那么我们如何获得绿色方法?你必须明确地将它包含在你的班级中:

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

但Ruby有另一个重要的用途。这是Mixin工具,我在SO的另一个答案中描述。但总而言之,mixins允许您将方法定义到对象的继承链中。通过mixins,您可以将方法添加到对象实例(包含)的继承链或self(extend)的singleton_class中。