Ruby基础教程(三)——类和模块

三、类和模块

  1. 什么是类

    • 类表示对象的种类。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. 继承

    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
      |==========|==========Time

    • is_a?方法——判断对象是否属于给定的类

      ary = []
      p ary.instance_of?(Array)   #==> true
      p ary.instance_of?(String)  #==> false
      p ary.instance_of?(Object)  #==> true   Object是ary的父类
  3. 创建类

    • 类名首字母必须大写

      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"
  4. 类方法

    方法的接收者为类本身,称为类方法

    • 方法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"
  5. 常量

    需要用::访问

    class Test
        Version = "1.0"
    end
    
    p Test::Version #==> "1.0"
  6. 类变量

    类变量以@@开头

    类变量被类的所有实例共享

    class Test
        @@cnt = 0
    end
  7. 限制方法

    public 全员公开(默认)

    private 对外不公开,只有内部的方法能够调用

    protected 内部的方法或子类可以调用,其他对象无法调用

    默认为public,但initialize方法默认为private

  8. 扩展类

    Ruby允许我们给定义好的类添加方法

    class String
        def count_word
            ary = self.split(/\s+/)  #==> 用空格分割
            return ary.size
        end
    end
    
    str = "David Wang Jordan"
    p str.count_word  #==> 3
  9. 继承类

    定义类时如果没有指定父类,Ruby默认该类为Object类的子类

    class NewArray < Array
    
    end

    instance_methods方法——返回该类的实例方法列表

    p "BasicObject", BasicObject.instance_methods
    
    #==> [:==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]
    
  10. 别名

    在重定义已经存在的方法时,可以用别名先把原先的方法保存起来,这样新旧方法都可以调用

    alias  别名   原名   #==>直接使用方法名
    alias :别名  :原名   #==>使用符号名
  11. 删除方法

    undef  方法名  #==> 直接使用方法名
    undef :方法名  #==> 使用符号名
  12. 单例类

    给该类的某个对象,定义专属的方法

    str1 = "David"
    str2 = "Wang"
    
    class << str1
        def test
            p "test"
        end
    end
    
    str1.test   #==> "test"
    str2.test   #==> 错误
  13. 模块

    • 简介

      类——数据+方法

      模块——只有方法

      模块不能拥有实例

      模块不能被继承

    • 创建/使用模块

      如果想把模块内定义的方法公开给外部使用,需要用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")
  14. 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,可以让多个类共享其他功能

  15. 查找方法的规则

    • 本类定义的方法 > 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]
  16. 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

你可能感兴趣的:(Ruby基础教程(三)——类和模块)