Crystal 中的模块有两个用途:
第一个用途是创建命名空间,以避免名称冲突。 不过,它也会把代码组织起来,让人更容易看懂代码的用途。
第二个用途是定义混入,把代码共享给各个类型。
模块和类很相似,但主要区别在于:模块不能被实例化,因此也没有实例变量。
要声明一个模块,使用module关键字,后面跟上模块的名字。
module Foo
end
命名空间是一种组织代码的方式。
这样可以避免名称冲突,也更容易看清代码的用途。
如果想访问放在某个命名空间里的常量或类,就要使用::运算符。
module Foo
class Bar
end
end
Foo::Bar.new
例如,当多个类需要相同的“基础”功能,或者需要在互不相关的类之间共享代码时,这就会很有用。 或者,当你想在不相关的类之间共享代码时,也可以这么做。
把模块用作混入有两种方式:第一种是使用include关键字,第二种是使用extend关键字。
两种方式都会让模块中的常量对包含或扩展该模块的类型可用。
包含会让模块中的所有方法都变成包含该模块的类型的实例方法。
include关键字应写在类型的顶部,后面跟上模块的名字。
module Foo
def foo
"foo"
end
end
class Bar
include Foo
end
Bar.new.foo # => "foo"
扩展的用法和包含类似,但它不会把方法变成实例方法,而是把它们变成类方法。
extend关键字应写在类型的顶部,后面跟上模块的名字。
module Foo
def foo
"foo"
end
end
class Bar
extend Foo
end
Bar.foo # => "foo"
Crystal 中一种常见的模式,是在模块里使用 extend self 模式。
这样,模块中的所有方法都会变成模块自身的类方法。
这意味着你不需要用def self.method_name语法把每个方法都挂到模块上。
module Foo
extend self
def foo
"foo"
end
end
Foo.foo # => "foo"