module ModuleA
constA = 'a'
end
class ClassA
p ModuleA::constA # => "a"
include ModuleA # 引入模块
p constA # => "a" # 直接在类中使用模块中的常量
end
Method
在类中引入模块后,其中的方法可以被该类的实例调用。
同时也可以在模块中将方法定义为模块方法。
module ModuleA
def method1
p "do method1.."
end
def method2
p "do method2.."
end
module_function :method2 # 将方法2设置为模型方法
end
class ClassA
include ModuleA
# 可以直接通过模型的命名空间调用模型方法
ModuleA.method2 # => "do method2.."
a = ClassA.new
a.method1 # => "do method1.."
end
module C
Name = 'lisi'
def hello(name)
p "#{Name} : hello," << name
end
# module_function :hello
end
module B
Name = 'zhangsan'
def self.hello(name)
p "#{Name} : hello," << name
end
# module_function :hello
end
class A
include C
include B
p Name # => "zhangsan"
B.hello "wangwu" # => "zhangsan : hello,wangwu"
# C.hello "wangwu" ## => 报NoMethodError (undefined method `hello' for C:Module)
a = A.new
a.hello "wangwu" # => "lisi : hello,wangwu" 因为在moduleB 中hello为自方法
end
include & extend
include添加一个模块的方法到实例中
extend添加一个模块的方法到类中
module Log
def class_type
"This class is of type: #{self.class}"
end
end
class TestClass
include Log
end
tc = TestClass.new.class_type
puts tc #This class is of type: TestClass
class TestClass
extend Log
# ...
end
tc = TestClass.class_type
puts tc # This class is of type: TestClass
module Foo
def self.included(base)
base.extend(ClassMethods)
end
def foo
puts 'instance method'
end
module ClassMethods
def bar
puts 'class method'
end
end
end
class Baz
include Foo
end
Baz.bar # class method
Baz.new.foo # instance method
Baz.foo # NoMethodError: undefined method ‘foo’ for Baz:Class
Baz.new.bar # NoMethodError: undefined method ‘bar’ for #<Baz:0x1e3d4>
module A
def A.included(mod)
puts "#{self} included in #{mod}"
end
end
module Enumerable
include A
end
# => prints "A included in Enumerable"
尤其值得注意的是,self其实就是调用的该类的一个单例类,可以从下面的例子看到:
car = "car"
class << car
def f1; puts "f1"; end
def self.f2; puts "f2"; end
class << self
def f3; puts "f3"; end
def self.f4; puts "f4"; end
end
end
car.f1 # => f1
car.singleton_class.f2 # => f2
car.singleton_class.f3 # => f3
car.singleton_class.singleton_class.f4 # => f4
class KLASS_IN
include Base;
end
KLASS_IN.hello_inm
# => NoMethodError (undefined method `hello_inm' for KLASS_IN:Class)
KLASS_IN.new.hello_inm
# => hello inm
此时在KLASS_IN的self方法和实例的方法中都不能找到hello_exm方法:
KLASS_IN.hello_exm
# => NoMethodError (undefined method `hello_exm' for KLASS_IN:Class)
KLASS_IN.new.hello_exm
# => NoMethodError (undefined method `hello_exm' for #<KLASS_IN:0x00007fbebd098610>)
可以先看一个例子:
module SelfM
def self.hello_self
puts "hello myself"
end
end
module Base
include SelfM;
extend SelfM;
end
Base.hello_self
# => NoMethodError (undefined method `hello_self' for Base:Module)
def append_features(base)
if base.instance_variable_defined?(:@_dependencies)
base.instance_variable_get(:@_dependencies) << self
return false
else
return false if base < self
@_dependencies.each { |dep| base.include(dep) }
super
# look here!
base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods)
base.class_eval(&@_included_block) if instance_variable_defined?(:@_included_block)
end
end
module InM
def hello_inm
puts 'hello inm'
end
end
module BaseModel
extend ActiveSupport::Concern
include InM
def hello_base
puts 'hello base module'
end
module ClassMethods
def hello_record
puts 'hello record'
end
end
end
class Re < ApplicationRecord
include BaseModel
end
Re.hello_record
# => hello record