Ruby中的方法我的总结

一切围绕方法的哲学

Ruby的一切,可以说是 —— 一切围绕方法。

面向对象是 数据+方法 的封装。而Ruby的变量不像JavaScript、Python允许自由的访问,必须在方法中通过设置 getter、setter来进行访问。可以说 方法是 Ruby工作的基石。

Ruby的方法有三大部分组成:

  1. 实例方法
  2. 类方法/单例方法
  3. 匿名函数方法

简单建立起概念,这三个基本方法,有自己的内涵边界。下面分别说明。

实例方法和类方法/单例方法,一起构成了面向对象系统

1.实例方法,非常容易理解。就是一般意义上的面向对象的为生成实例准备的方法。

表现形式是 class中直接定义的 def 方法。

1.1 实例方法和 inlcude

1) 继承关系 可以把一组方法,放入模块 比如 module B,然后 比如 class A include B。 这样在祖先链上会形成 A -> B 的关系。

1.2 搜索方法

实例搜索方法,当在A中无法找到的时候,会搜索B。

优先级顺序可以从 instance.class.ancestors 的返回中查看

1.3 覆盖方法

如果在A中定义的实例方法,会覆盖祖先方法,或者 module的mixin方法。

2.类方法/单例方法

严格意义上来说,应该是单例方法。

在类中,有很多中定义方式:


class A

  class << self
    def f
    end

  end


  def self.f

  end

  def A.f

  end

end


def A.f

end

这四种形式,定义的方法,都是 在单例类中保存方法。

对于类来说,结果的形式,就像是其他语言的类的静态方法。

所以直接理解为 类的静态方法,类方法,更加干脆清晰。

只不过 单例方法可以给任何对象定义。


obj = Object.new

def obj.f

end


这样子的定义是成立的。

2.1 extend 与 单例方法

和include对应,有个 extend关键字可以把 module中收集的方法,批量挂载到class上


module B

  def f

  end
end

class A
  extend f

  class << self

    def f
      # 这会覆盖 extend
    end
  end
end

2.2 覆盖

extend可以批量挂载类方法,class A 内部独立声明的 类方法会覆盖调 extend

2.3 搜索顺序

搜索顺序 instance.singleton_class.ancestors


对比总结下

特点\方法 实例方法 类方法/单例方法
说明 对象的实例的方法 可以认为是类的静态方法
拓展 include Module extend Module
继承方式 instance.class.ancestors instance.singleton_class.ancestors
覆盖 内部定义可覆盖 include 内部定义可覆盖 extend

匿名函数

匿名函数在Ruby里面呈现出很多形式

  1. 块(block)
  2. Proc类
  3. lambda
  4. method

这里细分的有点繁琐,但是总之他们就像匿名函数一样的存在。分别介绍下:

1.块(block)

一般是代码字面书写形式,具体有两种形式


xxx do 


end


xxx { }

2.Proc

与块对应的代码对象,有 Proc类,它相当于代码层面上的块,和lambda的区别在于,Proc类内部的return就像代码的return会直接带着环境返回,终止运行。

3.lambda

lambda 是特殊的Proc的实现,他表现的就像一个函数。是真正意义上和其他语言等价的 lambda 函数 —— 匿名函数

4.method

可以把一个对象实例的方法 unbind, 或者 通过 get method 的方式获得 一个类的具体方法,得到的就像一个匿名函数。

而且可以通过 binding 携带上下文执行。

拿JavaScript类比就像 function的call或者 apply


高级部分

Roda中看到的技巧。

include部分、extend部分,他们彼此可以互相覆盖,比如


class A

  include B1
  include B2
  include B3

  extend C1
  extend C2
  extend C3

end

这里,站在实例的角度 B1 B2 B3 等同于拓展 A 实例方法的插件。

站在类角度 C1 C2 C3 是拓展 A类方法的插件。

围绕着覆盖和根据约定使用核心方法,可以制造 —— “插件模式”。

总结

Ruby高度自由的动态性,元编程特性,主要focus在改变语言的构件。

而这些构件中,最最重要的就是 方法本身。

大部分的程序构建都在围绕 块/匿名函数方法、类方法、实例方法 展开。最复杂的部分也就是这样了。

一切万物归一,事情又变的非常简单。

其他讨论

1.为什么要建立那么多方法的概念?

我理解是为了封装

2.是否存在实例的实例方法?

其实大可不必钻牛角尖。

可以理解为,实例方法、类静态方法就是 90%的情况了。

单例类不可见。我们没法在上下文中优雅的为他们建立方法。于是一切就此打住,只有2层需要担心而已。

而复杂的继承模型可以通过 ancestors 相关的自省明确查找顺序。

Mark24

Everything can Mix.