你能告诉我我们应该在哪里使用模块和在哪里使用类吗?我的意思是 Ruby 中模块的可用性和适用性原则是什么?
6 回答
模块是方法和常量的集合。他们不能生成实例。类可以生成实例(对象),并具有每个实例的状态(实例变量)。模块可以混合到类和其他模块中。混合模块的常量和方法融入了该类自己的,增强了该类的功能。然而,类不能混入任何东西。一个类可以从另一个类继承,但不能从一个模块继承。一个模块不能继承任何东西。--红宝石常见问题解答
类是可靠的抽象,只包含重要的东西,模块是可以为我提供信息或服务的容器,此外还可以成为保持奇异性的地方。例如,我们可以对害羞的人进行分类,而胆怯是该分类的一个奇点。ShyPeople 可能是一个类,而 Timidity 可能是 ShyPeople 类中包含的一个模块。
'什么重要?','是模块的方法还是类的方法?或者“它会是一个类还是一个模块?” 是只有经验和 RL 的类比才能帮助你的问题。有关更多详细信息,我建议您阅读和编码 :)
我的简单经验法则是,如果我需要保持对象的内部状态,例如创建实例变量,我将使用一个类。
我将模块用于其他一切。这包括命名空间、mixin 和实用程序对象。
类是模块。不同之处在于可以实例化一个类。
两者的使用实际上取决于您的类/模块将如何使用,它代表什么,......
这个问题没有最终的答案。无论如何(恕我直言),这是您通过阅读和编写代码,学习习语,设计模式,...
本质上,Ruby 模块就像一个类,但没有对象工厂部分。通常 Ruby 开发人员使用模块来存储必须由多个类使用的方法组。除其他外,这是避免使用非常反红宝石模式的子类的好方法。
无论如何,这几乎是一个无法在短时间内正确回答的哲学问题。也许您应该尝试阅读有关 Ruby 基础知识的书(例如,Eloquent Ruby)。
在 ruby 中,模块由方法、变量和常量组成,类似于类,只是它缺乏实例化的能力。
模块通常包含或扩展在类中,具体取决于您希望如何公开和使用它包含的方法。如果您希望模块的方法、变量和常量在包含它的类的每个对象中都可用,则包含模块。如果您希望模块的方法、变量和常量对类可用而不是不可用,则扩展模块TO 类的实例。
Ruby 类采用单继承,即一个类只有一个父类/超类。但是,ruby 允许您通过在类中包含模块来“某种程度地”模拟多重继承,这个概念被称为 mixins。
模块用作命名空间和混合。Ruby 不支持多重继承。但是,在某些情况下,一个类会通过获取在多个其他类中定义的方法而受益。这可以通过使用称为模块的构造来实现。模块有点类似于类,只是它不支持继承,也不支持实例化。它主要用作存储多个方法的容器。使用模块的一种方法是在类中使用包含或扩展语句。这样,类就可以访问模块中定义的所有方法和对象。据说模块是混在课堂上的。因此,mixin 只是一个包含在类中的模块。单个模块可以混入多个类,单个类可以混入多个模块;因此,Ruby 施加的任何限制
所有模块都是 Module 类的实例。
module Foo
end
Foo.instance_of? Module # Output: => true
在下面的示例中,Person 类中包含 JapaneseGreetings 模块(作为 mixin)。
module JapaneseGreetings
def hello
puts "Konnichiwa"
end
def goodbye
puts "Sayōnara"
end
end
class Person
include JapaneseGreetings
end
p = Person.new
p.hello # Output: Konnichiwa
p.goodbye # Output: Sayōnara
类是模块
所有类都是名为 Class 的内置类的实例?好吧,Class 是 Module 的子类(另一个内置类)。
Class.superclass # Output: => Module
大多数用于操作类的内置方法都定义在 Module 类中。
Module.instance_methods(false)
=> [:<=>, :module_exec, :class_exec, :<=, :>=, :==, :===, :include?, :included_modules, :ancestors, :name,
:public_instance_methods, :instance_methods, :private_instance_methods, :protected_instance_methods, :const_get,
:constants, :const_defined?, :const_set, :class_variables, :class_variable_get, :remove_class_variable,
:class_variable_defined?, :class_variable_set, :private_constant, :public_constant, :singleton_class?,
:deprecate_constant, :freeze, :inspect, :module_eval, :const_missing, :prepend, :method_defined?, :class_eval,
:public_method_defined?, :private_method_defined?, :<, :public_class_method, :>, :protected_method_defined?,
:private_class_method, :to_s, :autoload, :autoload?, :instance_method, :public_instance_method, :include]
在超类中实现“通用”代码(可以在不同的上下文中使用)并在子类中添加额外的专业化是标准做法。一个例子是 Class 类如何从 Module 类继承所有上述实例方法并实现三个附加方法。
Class.instance_methods(false)
=> [:new, :allocate, :superclass]
allocate 方法分配内存并创建一个新的“空”类实例,而不调用 initialize 方法。新方法调用 allocate,然后在新创建的对象上调用 initialize 方法。至于超类,它返回给定类的超类的名称。
在他的《Ruby 编程语言》一书中,Yukihiro Matsumoto(Ruby 的创造者,AKA Matz)演示了如果用 Ruby 编写新方法会是什么样子:
def new(*args)
o = self.allocate # Create a new object of this class
o.initialize(*args) # Call the object's initialize method with our args
o # Return new object; ignore return value of initialize
end
简而言之,我们可以说类是具有两个重要的额外功能的模块:继承和实例化。另一个区别是,与模块不同,类不能用作混合。