Ruby OOP
ruby 是完全面向对象的语言
Class和对象
- Class 可以看作 method 的容器
- 对象是 可以对 method 作出响应的接收者
光说可能比较抽象, 看一下代码
class Car
def run
end
def name
end
end
_bmw = Car.new
puts Car.ancestors
# 会打印很多 ancestors 方法
puts _bmw.methods
# 打印的内容为空
puts _bmw.methods false
Car
作为一个class, 里面装着很多的方法.
而 _bmw
作为 Car的一个对象, 可以对 Car中的方法进行响应;
Car.ancestors
其中我们可以看到 Car 的继承关系
- Car
- Object
- Kernel
- BasicObject
_bmw中的很多方法都是在 ancestors
中定义好的
Module
Module(模块) 是不能创建自己的实例对象的;
它可以被mixin到别的Class里面.
因为, ruby 是一门非常动态的语言.
执行方法时, 依赖于运行时环境.
module Flue
def price
container_size * 7
end
end
class Container
include Flue
attr_accessor :container_size
def initialize(container_size = 0)
@container_size = container_size
end
end
_c = Container.new 2
puts _c.price
上面的代码中, module Flue
并没有定义 container_size
;
那么, 它怎么能够使用得到的呢?
它被嵌入到 Container
中, 取 Container 对象中的container_size.
module 的好处在于, 可以在多个Class中引入.
提供一种 组合的方式来构建class.
在软件开发中 组合是优于继承的
singleton_class
ruby 是一门面向对象的语言. 一切都是对象;
那么, 像 class Car
也是 Class 类的一个对象;
class Car
end
puts Car.class
输出的结果是 Class
;
我们知道了定义的class也是Class类的一个对象;
所有的method都应该有一个归属, 那么 class 中定义的类方法是放在哪里的呢?
class Car
def self.base_func
['run']
end
end
# false 表示只是Car定义的方法,不包括父类定义的
puts Car.methods false # []
# instance_methods 实例方法
puts Car.singleton_class.instance_methods false # [:base_func]
我们看到, Car中定义的类方法是 singleton_class
中存放的;
记住, ruby中 class, module 可以存放method, 对象是存放不了的;
那么, 有人可能会提出一种情况
str = ''
def str.foo
end
# str.foo 是 str的singleton_class的instance methods
puts str.singleton_class.instance_methods false
其实, 给对象定义一个只属于它的方法, 也是在 singleton_class
中定义的;
设想一下, 如果每一个对象都有自己的一个 singleton_class
那么,是不是有点浪费?
实际上,并不是每个对象都有 singleton_class 的;
只有你去使用时,才会创建一个;
这是对 singleton_class 方法的介绍
Returns the singleton class of obj.
This method creates a new singleton class if obj does not have one.
If obj is nil, true, or false, it returns NilClass, TrueClass, or FalseClass,
respectively. If obj is a Fixnum or a Symbol, it raises a TypeError.
method resolution (方法解析)
ruby 中定义一个方法可以在
- class
- module 通过include
- singleton_class
那么, 如果方法重名了, 会优先取哪个呢?
问题的重点是 取方法的顺序;
- singleton_class
- class 中定义的
- module 最后引入的
如下面的代码
module Flue
# 3.
def price
container_size * 7
end
end
class Container
include Flue
attr_accessor :container_size
def initialize(container_size = 0)
@container_size = container_size
end
# 2.
def price
99
end
end
_c = Container.new 2
# 1. 最优先
def _c.price
888
end
puts _c.price
程序设计
因为在开发中很多需求和功能都是需要逐渐完善的;
那么, 就会要求我们的代码是 changeable and extendable
能够轻松改变和拓展的;
在开发中,逐渐也了解了一些方法。 来提高代码的灵活性;
- 合理地拆分模块
- 通过module 来分享方法
- 单一职责的Class
- duck typing
- 多态替代判断
- 低耦合, 通过简单的对象传递 ,而非复杂的对象传递对象 (轻接口)
这里推荐看一下 马丁福乐的 《重构》里面讲了很多关于代码设计的内容;