三、类和模块
什么是类
类表示对象的种类。Ruby是完全面向对象的语言,一切都是对象,某个对象必属于某个类
class方法——给出某个对象所属的类
ary = [] a = 1 s = "string" p ary.class #==>Array p a.class #==>Fixnum p s.class #==>String
- instance_of?方法——判断对象是否是给定类的一个实例
ary = [] p ary.instance_of?(Array) #==> true p ary.instance_of?(String) #==> false p ary.instance_of?(Object) #==> false 虽然Object是ary的父类,但ary不是Object的实例
继承
2.1 继承的作用
在不影响原有功能的前提下追加新功能
重定义原有功能,使名称相同的方法产生不同的效果
在已有功能的基础上追加处理,扩展已有的功能
2.2 BasicObject类
BasicObject类是Ruby中所有类的父类
BasicObject类是最基础的类,只定义了最基础的方法。普通对象一般都是继承Object类
BasicObject
|
|==========Object
|==========|
|==========|==========Array
|==========|==========String
|==========|==========Hash
|==========|==========IO
|==========|==========|
|==========|==========|==========File
|==========|==========Regexp
|==========|==========Dir
|==========|==========Numeric
|==========|==========|
|==========|==========|==========Integer
|==========|==========|==========|
|==========|==========|==========|==========Fixnum
|==========|==========|==========|==========Bignum
|==========|==========|==========Float
|==========|==========|==========Complex
|==========|==========|==========Rational
|==========|==========Exception
|==========|==========Timeis_a?方法——判断对象是否属于给定的类
ary = [] p ary.instance_of?(Array) #==> true p ary.instance_of?(String) #==> false p ary.instance_of?(Object) #==> true Object是ary的父类
创建类
类名首字母必须大写
class 类名 类的定义 end
initialize方法
使用new方法创建对象时,initialize方法会被调用,new的参数会传给initialize方法
def initialize(myname = "Ruby" ) @name = myname end
实例变量
实例变量,就是类的成员变量,以“ @ ”开头
引用未初始化的实例变量时,返回值为nil
存取器
从对象外部不能直接访问实例变量,需要通过方法来完成
def name @name end def name= (value) @name = value end p bob.name #==> 获取name的值 p bob.name = "David" #==> 调用name=方法,像赋值一样
- 如果变量太多,每个变量都定义存取方法太麻烦,可以使用方法attr_reader, attr_write, attr_accessor
定义 意义 attr_reader 只读 attr_write 只写 attr_accessor 读写 class HelloWorld attr_reader :name attr_writer :address attr_accessor :phone end
- 特殊变量self
相当于C++的this
class Test attr_accessor :name def initialize(str = "David") @name = str end def show1 name = "XXX" p @name p name end def show2 p self.name end end t = Test.new() t.show1 #==> "David" #==> "XXX" t.show2 #==> "David"
类方法
方法的接收者为类本身,称为类方法
方法1
class << HelloWorld class << self def classFunc1(XXX) #==> 在类HelloWorld中,定义类方法 ... end def classFunc2(XXX) ... end end end
方法2
class Test end def Test.show p "show" end Test.show #==> "show"
方法3
class << Test def show p "show" end end Test.show #==> "show"
常量
需要用::访问
class Test Version = "1.0" end p Test::Version #==> "1.0"
类变量
类变量以@@开头
类变量被类的所有实例共享
class Test @@cnt = 0 end
限制方法
public 全员公开(默认)
private 对外不公开,只有内部的方法能够调用
protected 内部的方法或子类可以调用,其他对象无法调用
默认为public,但initialize方法默认为private
扩展类
Ruby允许我们给定义好的类添加方法
class String def count_word ary = self.split(/\s+/) #==> 用空格分割 return ary.size end end str = "David Wang Jordan" p str.count_word #==> 3
继承类
定义类时如果没有指定父类,Ruby默认该类为Object类的子类
class NewArray < Array end
instance_methods方法——返回该类的实例方法列表
p "BasicObject", BasicObject.instance_methods #==> [:==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]
别名
在重定义已经存在的方法时,可以用别名先把原先的方法保存起来,这样新旧方法都可以调用
alias 别名 原名 #==>直接使用方法名 alias :别名 :原名 #==>使用符号名
删除方法
undef 方法名 #==> 直接使用方法名 undef :方法名 #==> 使用符号名
单例类
给该类的某个对象,定义专属的方法
str1 = "David" str2 = "Wang" class << str1 def test p "test" end end str1.test #==> "test" str2.test #==> 错误
模块
简介
类——数据+方法
模块——只有方法
模块不能拥有实例
模块不能被继承
创建/使用模块
如果想把模块内定义的方法公开给外部使用,需要用module_function方法声明
模块函数中的self,返回的是使用该模块的类实例。在不同的情况下,self可能会不同,所以不建议在模块函数内部使用self
module 模块名 模块定义 end module HelloModule Version = 1.0 #==> 定义模块常量 def hello(name) p "Hello, #{name}." end module_function :hello #==> 指定hello方法为模块函数 end p HelloModule::Version HelloModule.hello("David") include HelloModule #==> 包含模块 p Version hello("Wang")
Mix-in
Mix-in就是用include语句,将模块混合到类中
include?方法——类是否包含某个模块
ancestors方法——获取继承关系列表
superclass方法——返回父类
module M end class C include M end p C.ancestors #==> [C, M, Object, Kernel, BasicObject] #==> Kernel是Ruby内部的一个核心模块,程序运行时所需的共通函数均在此模块内,例如p,raise等
Ruby不允许多重继承,但通过Mix-in,可以让多个类共享其他功能
查找方法的规则
本类定义的方法 > include模块中的方法 > 父类的方法
同一个类包含多个模块时,优先使用最后一个包含的模块
相同模块被包含两次以上时,第二次以后的会被省略
module M1 end module M2 end module M3 include M2 end class C include M1 include M3 end p C.ancestors #==> [C, M3, M2, M1, Object, Kernel, BasicObject]
extend方法
- include 通过模块扩展类的功能
- extend 通过模块扩展对象的功能
module Test end str = "" str.extend( Test )
module IncludeModule def include_method p "include_method" end end module ExtendModule def extend_method p "extend_method" end end class MyClass extend ExtendModule #==> 用extend定义类方法 include IncludeModule #==> 用include定义实例方法 end p MyClass.extend_method p MyClass.new.include_method