extend 和 extended

本章节我们将讲解第二种混入方式:extend

1. extend

extend可以扩展类或模块里面的方法,与include不同,extend扩展的是类方法(Class Method)。

实例:

module Person
  def name
    "My name is Andrew"
  end
end

class Member
  extend Person
end

puts Member.name

# ---- 输出结果 ----
My name is Andrew

解释:如上面输出结果展示的那样,扩展后,模块Person为类Member增加了一个名叫name的类方法(类方法是以类名直接调用的方法)。

除此之外对象也可以对模块进行extend,模块中的方法变成了实例方法(Instance Method),不过扩展的方法只针对一个对象有效。

实例:

module Person
  def name
    "My name is Andrew"
  end
end

class Member
  extend Person
end

member1 = Member.new
member2 = Member.new

member1.extend Person

puts member1.name
puts member2.name

# ---- 输出结果 ----
My name is Andrew
ruby.rb:17:in `<main>': undefined method `name' for #<Member:0x00007ff5688f1c08> (NoMethodError)

解释member1因为扩展了Person模块的方法,增加了实例方法name,而member2没有进行扩展,因此抛出了没有name方法的异常。

2. extended

当我们extend一个模块的时候,就会触发模块的extended回调函数。

让我们修改一下上面的实例。

实例:

module Person
  def self.extended(klass)
    puts "#{klass} extended #{self}"
  end
  
  def name
    "My name is Andrew"
  end
end

class Member
  extend Person
end

puts Member.name

# ---- 输出结果 ----
Member extended Person
My name is Andrew

解释:当模块Person被扩展后,会触发extended钩子方法,率先打印了“Member extended Person”。

3. 小结

本章节我们学习了extend,当类或模块extend一个模块的时候,会将模块中定义的方法填充进类或模块的类方法中,另外,当一个模块被extend的时候,会触发extended回调,并返回操作的类名。