脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Ruby - Ruby的面向对象方式编程学习杂记

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

2020-05-09 10:17日拱一卒 Ruby

Ruby是具有面向对象特性的编程语言,这里整理了一些Ruby的面向对象方式编程学习杂记,包括类与方法等基本的面向对象要素的知识,需要的朋友可以参考下

打开类

可以重新打开已经存在的类并对之进行动态修改,即使像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角色

对象、类与模块之间关系

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

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

动态方法

动态调用方法

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

示例代码
 

?
1
2
3
4
5
6
7
8
9
class MyClass
  def my_method(my_arg)
    my_arg * 2
  end
end
 
obj = MyClass.new
obj.my_method(3#=> 6
obj.send(:my_method, 3) #=> 6

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

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

动态定义方法

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

示例代码

?
1
2
3
4
5
6
7
8
class MyClass
  define_method :my_method do |my_arg|
    my_arg * 3
  do
end
 
obj = MyClass.new
obj.my_method(2) #=> 6

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

method_missing方法

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

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

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

示例代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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}"
 end
end
 
number_of = Roulette.new
puts number_of.bob
puts 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方法(方法特别多的情况),否则尽量少使用它。

延伸 · 阅读

精彩推荐
  • RubyRuby中对一元操作符重载实例

    Ruby中对一元操作符重载实例

    这篇文章主要介绍了Ruby中对一元操作符重载实例,实例说明如何对一元操作符进行重载,需要的朋友可以参考下 ...

    junjie1852020-04-14
  • RubyWindows下ruby语言安装教程

    Windows下ruby语言安装教程

    这篇文章主要介绍了Windows下ruby语言安装教程,本文使用rubyinstaller提供的安装包安装,并给出图文说明,非常简单,需要的朋友可以参考下 ...

    脚本之家5522020-04-22
  • Ruby深入讲解Ruby中Block代码块的用法

    深入讲解Ruby中Block代码块的用法

    这篇文章主要介绍了深入讲解Ruby中Block代码块的用法,block是Ruby学习进阶当中的重要知识,需要的朋友可以参考下 ...

    pringwq4582020-04-27
  • RubyRuby on Rails所构建的应用程序基本目录结构总结

    Ruby on Rails所构建的应用程序基本目录结构总结

    Ruby on Rails是Ruby世界中一家独大的Web开发框架,要掌握Rails程序的构建,对其目录结构的了解十分必要,下面就来看一下Ruby on Rails所构建的应用程序基本目录结...

    kevinhua4002020-05-09
  • Ruby对Ruby on Rails进行高效的单元测试的教程

    对Ruby on Rails进行高效的单元测试的教程

    这篇文章主要介绍了在Ruby on Rails中进行高效的单元测试的教程,使用到了Ruby的RSpec和Factory Girl框架,需要的朋友可以参考下 ...

    李冠德3562020-04-26
  • Rubyruby实现修改ubuntu下的hosts

    ruby实现修改ubuntu下的hosts

    本文给大家分享的是通过ruby获取github上的hosts文件内容,修改到本地Ubuntu中,十分的实用,具体你懂得,有需要的小伙伴可以参考下。 ...

    脚本之家3882020-05-03
  • RubyRuby学习笔记之gem 命令详解

    Ruby学习笔记之gem 命令详解

    gem是一种文件组织的包,一般的ruby的很多插件都有由这种各种的包提供。我们来看看gem的用法 ...

    hebedich8662020-04-16
  • RubyRuby编程中关于中断和返回的用法教程

    Ruby编程中关于中断和返回的用法教程

    这篇文章主要介绍了Ruby编程中关于中断和返回的用法教程,作者用代码举例讲解了其中需要注意的问题,需要的朋友可以参考下 ...

    李哲3142020-04-27