Ruby元编程-学习笔记(一)-对象模型

打开类

可以重新打开已经存在的类并进行动态修改,即便是标准类库也不例外

class String
    def my_method
        puts "This is my_method()"
    end
end
"str".my_method     #=> This is my_method()
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这种方式是不是很方便? 当然凡事都有利弊,带来方便的同时也给我们带来了一些问题:可能会对于类中已有的方法进行覆盖,为了修复这样的问题所使用的patch称为猴子补丁.

"A".downcase    #=> "a"
class String
    def downcase
        puts "This is downcase() method"
    end
end
"A".downcase    #=> This is downcase() method
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

所以,虽然打开类技术非常方便,但是由于若是乱用可能会导致很大的问题.

类与对象

1. 对象中有什么

class MyClass
    def my_method
        @v = 1
    end
end
obj = MyClass.new
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 实例变量

    与一般静态语言不同,Ruby中的对象的类和它的实例变量没有关系,当给实例变量赋值时,它们才会产生. 
    obj.instance_variables #=>[] 
    obj.my_method 
    obj.instance_variables #=>[:@v]

  • 方法

    除了实例变量,对象还有方法,虽然可以利用methods方法查看到对象所拥有的方法,但实际上对象并没有存放这些方法,而是存放一个对自身类的引用.而这些方法存放在类中,称之为实例方法,与类方法截然不同.实例方法必须是类的实例才能调用,而类方法必须是类本身才能调用. 
    String.instance_methods == "abc".methods #=>true 
    String.methods == "abc".methods #=>false

总结: 一个对象的实例变量存在与对象本身,而一个对象的方法存在与对象自身的类.这也是为什么同一个类的对象共享者同样的方法,但不共享实例变量的原因.

2. 类

  • 类自身也是对象
"Hello".class   #=> String
String.class    #=> Class
 
 
  • 1
  • 2

一个对象的方法也就是其类的实例方法,也就是说一个类的方法就是Class的实例方法

Class.instance_methods(false) #=>[:superclass,:allocate,:new]

new()方法用于创建对象
allocate()方法是new()的支撑方法
superclass()返回一个类的超类
 
 
  • 1
  • 2
  • 3
  • 4
  • 5

所有类最终都继承与Object,Object本身又继承与BasicObject, BasicObject是Ruby对象体系中的根结点.

String.superclass       # => Object
Object.superclass       # => BasicObject
BasicObject.superclass  # => nil

class.superclass        # => Module
Module.superclass       # => Object
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

所以,一个类不过是一个增加了三个方法的Module.类和模块基本上是一样的,绝大多数适用于类的情况也同样适用于模块,反之亦然.

class MyClass ; end
obj1 = MyClass.new
obj2 = MyClass.new
 
 
  • 1
  • 2
  • 3

上述代码的模型图如下: 
类就是对象

load 与require

使用load(‘test.rb’)可引用外部代码, 但对于test.rb文件所定义的变量和类会落在当前作用域之外,而常量则会落在当前作用域之类,这样便会污染当前程序的命名空间,不过可使用load(‘test.rb’, true)强制其常量仅在自身范围内有效. 
require() 方法与load()相似,但load可以执行代码,而require则是导入类库

总结: 
类就是对象,只不过类名是常量[任何以大写字母开头的引用,包括类名和模块名].

方法调用

当调用一个方法时, Ruby会做两件事 
1. 找到这个方法, 需要祖先链 
2. 执行这个方法, 需要self

1.方法查找

  • 接收者 : 即为调用方法所在的对象, 如obj.method()中,obj即为接收者

  • 祖先链 : 从当前类一直向上寻找超类直到找到BasicObject 类所经过的路径,即为祖先链(亦包括模块).

方法查找: 首先在接收者的类中查找,然后一层层在祖先链中查找,直到找到该方法为止.

class MyClass
    def my_method; 'my_method()'; end
end
class MySubClass < MyClass 
end

obj = MySubClass.new
obj.my_method()

MySubClass.ancestors  # =>[MySubClass, MyClass, Object, Kernel, BasicObject]
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

当在一个类(或模块)中包含一个模块时,Ruby创建一个封装该模块的匿名类,并将其插入到祖先链中.

module M
    def my_method
        'M#my_method()'
    end
end
class C
    include M
end
class D < C; end

D.new.my_method()   # => "M#my_method()"
D.ancestors # => [D, C, M, Object, Kernel, BasicObject]
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
Kernel模块

如果给Kernel模块增加一个方法,这个内核方法就对所有对象可用. 
这里写图片描述

2.方法执行

  • 探索self

每一行代码都会在一个当前对象中执行,可使用self关键字访问当前对象.当调用一个方法时,接收者就成为self, 这时所有的实例变量都是self 的实例变量,搜偶没有明确指明接收者的方法都在self上调用.

  • 类定义与self

self通常由最后一个接受到方法的对象充当,但在类或模块定义中[任意方法定义之外], self由这个类或模块充当.

class MyClass
    def self.my_method  # =>类方法,self代表MyClass
        puts "self is #{self}"
    end
    def my_method   # =>实例方法, self为接收者
        puts "self is #{self}"
    end
end

MyClass.my_method       # =>self is MyClass
obj = MyClass.new
obj.my_method           # =>self is obj
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 私有private

不能明确指定一个接收者来调用一个私有方法, 但可通过send方法破坏私有性

小结

  • 对象由一组实例变量和一个类的引用组成
  • 对象的方法存在与自身的类中,称之为实例方法
  • 类本身是Class类的实例,类名即为常量
  • Class类是Module的子类,一个模块是有一组方法组成的包.
  • 常量像文件系统一样,按照树形结构组织, 其模块和类的名字扮演目录的角色, 其它普通常量则扮演文件的角色.
  • 每一类都有一个祖先链, 从自己所属类开始直到BasicObject结束
  • 当调用一个方法时,Ruby会先向右来找到所属类,然后沿着祖先链向上查找
  • 每当类包含一个模块时, 该模块会被插入到祖先链中, 位于该类的正上方
  • 当调用一个方法时, 接收者会扮演self角色
  • 当定义一个模块或类时, 该模块或类扮演self角色
  • 实例变量永远被认定为self的实例变量
  • 任何没有明确指定接收者的方法调用,都是调用self的方法
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值