打开类
可以重新打开已经存在的类并对之进行动态修改,即使像String或者Array这样标准库的类也不例外。这种行为方式称之为打开类(open class)
猴子补丁
如果你粗心地为某个类添加了新功能,同时覆盖了类原来的功能,进而影响到其他部分的代码,这样的patch称之为猴子补丁(Monkeypatch)
类与模块
Ruby的class关键字更像是一个作用域操作符,而不是类型声明语句。class关键字的核心任务是把你带到类的上下文中,让你可以在里面定义方法。
每个类都是一个模块,类就是带有三个方法(new,allocate,superclass)的增强模块,通过这三个方法可以组织类的继承结构,并创建对象
Ruby中的类和模块的概念十分接近,完全可以将二者相互替代,之所以同时保留二者的原因是为了保持代码的清晰性,让代码意图更加明确。使用原则:
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 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方法和代码块提供了动态方法定义方式
示例代码
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方法,对相似的方法进行统一做出回应,这样一来其行为就类似与调用定义过的方法一样。
示例代码
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只删除接受者自己的方法,而保留继承来的方法。
动态方法与Method_missing的使用原则
当可以使用动态方法时候,尽量使用动态方法。除非必须使用method_missing方法(方法特别多的情况),否则尽量少使用它。
本文向大家介绍Python的面向对象编程方式学习笔记,包括了Python的面向对象编程方式学习笔记的使用技巧和注意事项,需要的朋友参考一下 类与实例 类与实例相互关联着:类是对象的定义,而实例是“真正的实物”,它存放了类中所定义的对象的具体信息。 下面的示例展示了如何创建一个类: 关键字是 class,紧接着一个类名。随后是定义类的类代码。这里通常由各种各样的定义和声明组成。新式类和经典类声明的最
本文向大家介绍Ruby面向对象编程中类与方法的基础学习,包括了Ruby面向对象编程中类与方法的基础学习的使用技巧和注意事项,需要的朋友参考一下 打开类和猴子补丁 在Ruby中,类定义的方法和其他的语句没有任何区别,都是一行一行的执行下去的。如下例子: 本例中,当第一次定义Class Example的时候,还没有一个叫做Example的Class存在,因此,Ruby开始定义这个类,当后面在定义这个类
本文向大家介绍Ruby面向对象编程详解,包括了Ruby面向对象编程详解的使用技巧和注意事项,需要的朋友参考一下 Ruby是纯面向对象的语言,所有项目似乎要Ruby中为一个对象。Ruby中的每个值是一个对象,即使是最原始的东西:字符串,数字甚至true和false。即使是一个类本身是一个对象,它是Class类的一个实例。本章将通过所有功能涉及到Ruby的面向对象。 类是用来指定对象的形式,它结合了数
本文向大家介绍Python语言的面相对象编程方式初步学习,包括了Python语言的面相对象编程方式初步学习的使用技巧和注意事项,需要的朋友参考一下 词语练习 class:告诉python创造一个新的东西 object:两个意思:最基本的东西和任何实例化的东西。 instance:创建一个类得到的东西。 def:在类中创建一个函数。 self:在类里面的函数中使用,是实例和object能访问的变量。
本文向大家介绍Python面向对象编程中关于类和方法的学习笔记,包括了Python面向对象编程中关于类和方法的学习笔记的使用技巧和注意事项,需要的朋友参考一下 类和实例 python是一个面向对象的语言,而面向对象最重要的概念就是类和实例, 记得刚学习的时候不太理解这些概念,直到老师说了一句”物以类聚”. 没错就是类, 归类 物以类聚 类其实就是把一些相同特性的事物归成一类, 比如人 我们定义了人
我们已经讨论了类/对象可以拥有像函数一样的方法,这些方法与函数的区别只是一个额外的self变量。现在我们来学习一个例子。 使用对象的方法 例11.2 使用对象的方法 #!/usr/bin/python # Filename: method.py classPerson: defsayHi(self): print'Hello, how are you?' p = Perso