类和模块的区别

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

我不熟悉的一个语言特性是module。我想知道到底什么是module,什么时候使用一个,为什么使用module而不是class?

164392 次浏览

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

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


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

第一个答案很好,给出了一些结构性的答案,但另一种方法是思考你在做什么。模块提供了可以跨多个类使用的方法——可以把它们看作“库”(就像你在Rails应用程序中看到的那样)。类是关于对象的;模块是关于函数的。

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

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

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

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

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

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

类就像Java类一样简单。

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

总结:模块是静态/实用类和mixin之间的交叉。

Mixins是“部分”实现的可重用片段,可以在mix &中组合(或组合);匹配样式,以帮助编写新类。当然,这些类还可以有自己的状态和/或代码。

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

模块

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

  • 模块给你两个主要的好处:

    模块提供命名空间,防止名称冲突。

    .命名空间有助于避免与他人编写的同名函数和类冲突

    =>模块实现了mixin设施

(在Klazz中包含模块使Klazz的实例可以访问Module 方法。)< / p >

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

首先,一些相似之处还没有被提及。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)中添加方法。

名称空间:模块是命名空间…这在Java中是不存在的;)

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

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

所以ruby中的模块就像java中的一样:
课吗?没有< br > 接口?没有< br > 抽象类?没有< br > 包吗?是的(可能)

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

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

那么模块中包含什么?< br > 类,方法,常量。模块在该名称空间下保护它们。< / p >

没有实例:模块不能用于创建实例

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

ruby中关于模块的规则:
—模块名称为“UpperCamelCase
” -模块中的常量都是ALL CAPS(这条规则对所有ruby常量都是一样的,而不是特定于模块)
—访问方式:使用。操作符< br > —访问常量: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文件一个类)