当前位置: 首页 > news >正文

【Ruby】Mixins扩展方式之include,extend和prepend

Mixin定义

首先,mixin是module模块,它用于在class之间共享提供可复用的的方法而不采用继承的方式。
通常在Ruby中用module来创建mixins,示例如下:

module Greetabledef greet"Hello!"end
end

不同于继承,可以将这个module通过mixin方式(include, extend, prepend)进任何的class。

3种方式使用Mixin

include—混入为实例方法

当使用include,对应module的方式会变成class的实例方法,示例如下:

module Greetabledef greet"Hello!"end
endclass Personinclude Greetable
endp = Person.new
puts p.greet  # => "Hello!"

此时Ruby会把模块插入到类的继承链中,对应的位置是类的父类之前,可通过如下查看:

Person.ancestors
# => [Person, Greetable, Object, Kernel, BasicObject]
extend—混入为类方法(单例方法)

使用extend时,模块中的方法会变成类方法,示例如下:

module Identifiabledef identity"I’m a class method!"end
endclass Robotextend Identifiable
endputs Robot.identity
# => "I’m a class method!"

此时Ruby会把模块混入到对象的单例方法中,这样模块的方法就成为了这个对象的自身的方法。

prepend—类似include,顺序不同

prepend也会把模块混入为实例方法,但与include方法不同的是,模块会被插入到类之前,因此模块的方法可以覆盖类自身的方法,同时还能通过super调用原方法。示例如下:

module Loggingdef greetputs "Logging: greet was called"superend
endclass Userdef greet"Hello from User"endprepend Logging
endu = User.new
puts u.greet

输出结果如下:

Logging: greet was called
Hello from User

此时查看继承链如下所示:

User.ancestors
# => [Logging, User, Object, Kernel, BasicObject]

因此ruby会先调用Logging#greet,然后在其中通过super调用User#greet。

三者比较如下:

功能includeextendprepend
添加的方法类型实例方法类方法(单例方法)实例方法
方法查找顺序类 → 模块 → 父类单例类 → 模块模块 → 类 → 父类
常见用途添加实例行为添加类级行为覆盖或拦截原有方法
示例场景EnumerableComparableRails 的 ClassMethods 模块日志、监控、拦截器等

实际应用场景

通过上述过程可以发现,Ruby查找方法时,不同混入方式会改变模块在继承链中的位置从而改变查找的顺序。

include应用
class VowelFinderinclude Enumerabledef each@string.scan(/[aeiou]/) { |v| yield v }end
end

Enumerable 一个模块(mixin),它提供map、reduce、select等功能,但要求类中必须定义一个each方法,一旦定义了each,Enumerable的所有方法就能自动工作。这就是 include 的经典用法 —— 给实例增加集合行为。

extend应用

Rails中的模块经常会在include的同时自动extend类,以添加类方法。示例如下:

module Trackabledef self.included(base)base.extend ClassMethodsendmodule ClassMethodsdef trackedputs "Tracking enabled for #{self.name}"endend
endclass Userinclude Trackable
endUser.tracked  # => "Tracking enabled for User"
perpend应用

Rails、Devise、ActiveRecord等框架中经常使用prepend来在核心方法前后插入逻辑。示例如下:

module Auditdef saveputs "Audit: saving record..."superend
endclass Modeldef saveputs "Saving to DB"endprepend Audit
endModel.new.save
# => Audit: saving record...
# => Saving to DB

prepend允许在不修改原方法的情况下,对其进行包装、拦截、增强。

http://www.dtcms.com/a/581606.html

相关文章:

  • 欧美 电台 网站模板4防伪查询网站
  • MTK外包面经
  • [linux] grep命令的使用
  • 前后端跨域问题解决
  • 通往AGI的模块化路径:一个可能的技术架构(同时解答微调与RAG之争)
  • cartographer ros 配置详解
  • 告别人工登高 无人机智能巡检平台让效率提升300%
  • docker登录ghcr.io
  • 网站评估 源码wordpress 建立数据库连接时出错 用户名密码可能不正确
  • 划清界限:深度解读EUDR法案的适用范围,谁将受到冲击?
  • 数据结构初阶:Java中的Stack和Queue
  • Node.js环境变量配置的实战技术
  • 帮人做网站赚多少钱邯郸市内最新招聘信息
  • 提问:Flutter 项目在浏览器中运行失败是怎么回事?
  • Node.js 多进程
  • 基于spark岗位招聘推荐系统 基于用户协同过滤算法 Django框架 数据分析 可视化 大数据 (建议收藏)✅
  • 《Flutter全栈开发实战指南:从零到高级》- 12 -状态管理Bloc
  • 装饰工程东莞网站建设百度seo外包
  • CSS 提示工具:高效开发利器
  • IDE 开发的一天
  • Jwt令牌、过滤器、拦截器快速入门
  • 做画找图网站网站建设的公司合肥
  • h5支付宝支付 - 支付宝文档中心1.登录 支付宝开放平台 创建 网页/移动应用
  • Java八股—MySQL
  • 网站显示目录北京网站建设华大
  • Go中的泛型编程和reflect(反射)
  • Go Ebiten小游戏开发:扫雷
  • TransformerLLM(大语言模型)的核心底层架构
  • 网站设计的毕业设计百度建设网站
  • 【GitHub热门项目】(2025-11-07)