我来自Java,现在我更多地使用Ruby。

我不熟悉的一个语言特性是模块。我想知道究竟什么是模块,什么时候使用模块,为什么使用模块而不是类?


当前回答

定义类时,就是为数据类型定义了蓝图。 类保存数据,具有与该数据交互的方法,并用于实例化对象。

模块

模块是将方法、类和常量分组在一起的一种方式。 模块给你两个主要的好处: 模块提供名称空间,防止名称冲突。 命名空间有助于避免与其他人编写的同名函数和类发生冲突。 模块实现了mixin功能。

(包括在Klazz中的Module,可以让Klazz的实例访问Module 方法。) (用Mod扩展Klazz,使类Klazz可以访问Mods方法。)

其他回答

我很惊讶居然还没人这么说。

由于提问者有Java背景(我也有),这里有一个类比。

类就像Java类一样简单。

模块类似于Java静态类。想想Java中的Math类。你不实例化它,你重用静态类中的方法(例如。math . random())。

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

但你需要问自己,在编程语言中同时拥有类和模块的目的是什么?类旨在成为创建实例的蓝图,而每个实例都是该蓝图的实现变体。实例只是蓝图(类)的实现变体。自然地,类的功能是创建对象。此外,由于我们有时希望一个蓝图从另一个蓝图派生,所以类被设计为支持继承。

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

那么在语言中使用模块的意义是什么呢?Modules的一个明显用途是创建名称空间,在其他语言中也会注意到这一点。再说一遍,Ruby最酷的地方在于模块可以被重新打开(就像类一样)。当你想在不同的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模块继承任何方法,当我们在Fruit类中包含Apple时,Apple模块的方法被添加到Apple实例的祖先链中,而不是Green模块的方法,即使Green模块是在Apple模块中定义的。

那么我们如何使用绿色方法呢?你必须明确地将它包含在你的类中:

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

但是Ruby对模块还有另一个重要的用途。这是Mixin设施,我在关于SO的另一个回答中描述了它。但总的来说,mixin允许在对象的继承链中定义方法。通过mixin,您可以向对象实例的继承链(include)或self的singleton_class (extend)中添加方法。

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

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


(这个答案最初链接到http://www.rubycentral.com/pickaxe/classes.html,但该链接及其域名已不再有效。)

定义类时,就是为数据类型定义了蓝图。 类保存数据,具有与该数据交互的方法,并用于实例化对象。

模块

模块是将方法、类和常量分组在一起的一种方式。 模块给你两个主要的好处: 模块提供名称空间,防止名称冲突。 命名空间有助于避免与其他人编写的同名函数和类发生冲突。 模块实现了mixin功能。

(包括在Klazz中的Module,可以让Klazz的实例访问Module 方法。) (用Mod扩展Klazz,使类Klazz可以访问Mods方法。)

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