侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Ruby的面向对象方式编程学习杂记

技术  /  管理员 发布于 6年前   300

打开类

可以重新打开已经存在的类并对之进行动态修改,即使像String或者Array这样标准库的类也不例外。这种行为方式称之为打开类(open class)

猴子补丁

如果你粗心地为某个类添加了新功能,同时覆盖了类原来的功能,进而影响到其他部分的代码,这样的patch称之为猴子补丁(Monkeypatch)

类与模块

Ruby的class关键字更像是一个作用域操作符,而不是类型声明语句。class关键字的核心任务是把你带到类的上下文中,让你可以在里面定义方法。

每个类都是一个模块,类就是带有三个方法(new,allocate,superclass)的增强模块,通过这三个方法可以组织类的继承结构,并创建对象

Ruby中的类和模块的概念十分接近,完全可以将二者相互替代,之所以同时保留二者的原因是为了保持代码的清晰性,让代码意图更加明确。使用原则:

  • 希望把自己代码包含(include)到别的代码中,应该使用模块
  • 希望某段代码被实例化或被继承,应该使用类
  • 模块机制可以用来实现类似其它语言中的命名空间(Namespace)概念

Ruby中的::符号

Ruby中常量的路径(作用域),类似与文件系统中的目录,通过::进行分割和访问,默认直接以::开头(例: :: Y)表示变量路径的根位置

什么是对象

对象就是一组实例变量外加一个指向其类的引用。对象的方法并不存在于对象本身,而是存在于对象的类中。

什么是类

类就是一个对象(Class类的一个实例)外加一组实例方法和一个对其超类的引用。Class类是Module类的子类,因此一个类也是一个模块。

load与require方法的异同

通过load和require都可以进行导入别人的代码,不同的是load方法用来加载代码,如果不希望污染当前的命名空间,需要通过load(‘file.rb',true)显式的要求创建一个匿名模块来,接管file.rb的常量,require用于导入类库,此外,就加载次数上load方法每次调用都会再次运行所加载文件,require则对每个库文件只加载一次。

prepend、include与祖先链

祖先链用于描述Ruby对象的继承关系,因为类与模块是父子关系,所以祖先链中也可以包含模块,prepend与include分别可以向链中添加模块,不同的是调用include方法,模块会被插入祖先链,当前类的正上方,而prepend同样是插入到祖先链,但位置其他却在当前类的正下方,另外通过Class.ancestors可以查看当前的祖先链

private规则

不能通过明确指定接受者来调用私有方法。私有方法只能通过隐性的接受者self调用(Object#send是个例外)

self相关

调用一个方法时,接受者会扮演self角色 任何没有明确指定接受者的方法调用,都当做是调用self的方法 定义一个模块(或类)时,该模块(或类)会扮演self角色

对象、类与模块之间关系

上面Module.class指向的也是Class类,可以理解为上面方框内容均为Class,但他们的父子组织关系通过superclass建立并存在异同,可以通过Class.ancestors查看。

动态方法

动态调用方法

在Ruby中通过Object#send方法可以代替点标识调用对象的指定实例方法

示例代码
 

class MyClass  def my_method(my_arg)    my_arg * 2  endendobj = MyClass.newobj.my_method(3)  #=> 6obj.send(:my_method, 3) #=> 6

上面代码通过直接调用和使用send方法调用得到的结果是一样的,使用send的好处是,可以在编码中,动态的决定方法调用。这个技巧在元编程中被称为动态派发

另外需要指出的地方是通过Object#send不仅可以调用公共方法,也可以调用对象的私有方法。如果想保留对象的封装特性,不向外暴露私有方法可以使用Object#public_send方法。

动态定义方法

除了方法的动态调用之外,Ruby还通过Module#define_method方法和代码块提供了动态方法定义方式

示例代码

class MyClass  define_method :my_method do |my_arg|    my_arg * 3  doendobj = MyClass.newobj.my_method(2) #=> 6

上面代码通过define_method方法取代了关键词def,其本质上都是相同的,只是在定义方式上,define_method的方式更加灵活一些,可以通过在编码中通过推导,完成函数的定义,增加了实现的灵活性。

method_missing方法

严格意义上将method_missing方法,并不算是明确的定义(不会出现在methods列表中),其本质是通过方法查找的机制来截获调用信息进而合理的给出相应方法的回应。有点类似与异常处理中的抛出异常,一层一层的往外抛。

method_missing利用的机制是,当一个对象进行某个方法调用的时候,会到其对应的类的实例方法中进行查找,如果没有找到,则顺着祖先链向上查找,直到找到BasicObject类为止。如果都没有则会最终调用一个BasicObject#method_missing抛出NoMethodError异常。

当我们需要定义很多相似的方法时候,可以通过重写method_missing方法,对相似的方法进行统一做出回应,这样一来其行为就类似与调用定义过的方法一样。

示例代码

class Roulette def method_missing(name, *args)  person = name.to_s.capitalize  super unless %w[Bob Frank Bill Honda Eric].include? person  number = 0  3.times do   number = rand(10) + 1   puts "#{number}..."  end  "#{person} got a #{number}" endendnumber_of = Roulette.newputs number_of.bobputs number_of.kitty

动态代理

对一些封装过的对象,通过method_missing方法收集调用,并把这些调用转发到被封装的对象,这一过程称为动态代理,其中method_missing体现了动态,转发体现了代理

const_missing方法

与method_missing类似,还有关于常量的const_missing方法,当引用一个不存在的常量时,Ruby会把这个常量名作为一个符号传递给const_missing方法。

白板类(blank slates)

拥有极少方法的类称为白板类,通过继承BasicObject类,可以迅速的得到一个白板类。除了这种方法以外,还可以通过删除方法来将一个普通类变为白板类。

删除方法

删除某个方法有两种方式:

  • Module#undef_method
  • Module#remove_method

二者的区别是Module#undef_method会删除所有(包括继承而来的)方法。而Module#remove_method只删除接受者自己的方法,而保留继承来的方法。

动态方法与Method_missing的使用原则

当可以使用动态方法时候,尽量使用动态方法。除非必须使用method_missing方法(方法特别多的情况),否则尽量少使用它。


  • 上一条:
    Lua中的string库(字符串函数库)总结
    下一条:
    CSS margin全面了解
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 2024.07.09日OpenAI将终止对中国等国家和地区API服务(0个评论)
    • 2024/6/9最新免费公益节点SSR/V2ray/Shadowrocket/Clash节点分享|科学上网|免费梯子(1个评论)
    • 国外服务器实现api.openai.com反代nginx配置(0个评论)
    • 2024/4/28最新免费公益节点SSR/V2ray/Shadowrocket/Clash节点分享|科学上网|免费梯子(1个评论)
    • 近期文章
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-07
    • 2017-08
    • 2017-09
    • 2018-01
    • 2018-07
    • 2018-08
    • 2018-09
    • 2018-12
    • 2019-01
    • 2019-02
    • 2019-03
    • 2019-04
    • 2019-05
    • 2019-06
    • 2019-07
    • 2019-08
    • 2019-09
    • 2019-10
    • 2019-11
    • 2019-12
    • 2020-01
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2020-10
    • 2020-11
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-04
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-12
    • 2024-02
    • 2024-04
    • 2024-05
    • 2024-06
    • 2025-02
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客