Ruby 基础学习笔记(纯粹的面向对象 方法 module 闭包 变量范围)

 
---------------------------------------------------------------------------------------------------------------------------------------------------------

#About objects,instance variables,and methods.
对象的实例变量被存储在对象里面,实例方法通过对象的object_id到对象的class里面查找实例法
#methods()
返回该对象的所有能respond_to?的方法
#instance_methods: (Only instance can use them)
返回该对象的所有public,protected的实例方法
#private method
私有方法只能直接调用方法名而且当前self变量的值必须为其声明的对象值
---------------------------------------------------------------------------------------------------------------------------------------------------------
ruby的module主要用于mixin(解决多重继承的问题)扩展方法和用于命名空间
当需要一个被继承或者能实例化的对象时才用class
module的优劣:(待完善)
--------------------------------------------------------------------------------------------------------------------------------------------------------

module MyModule
  MyConstant = 'Outer constant'

  class MyClass
    MyConstant = 'Inner constant'
  end
end

静态变量在modules和classes里面存储模式类似于文件夹(modules,classes)与文件(constant)的方式
故在不同文件夹下同名文件也不会冲突。
---------------------------------------------------------------------------------------------------------------------------------------------------------

load() 每次都会重新加载文件,并执行里面的码。
require() 只加载一次,加载的模式相当于import进来一个库。
#当应用load("filename", ture) 时加载进来的文件将放在一个匿名module里面,用完之后销毁匿名modue(目的是阻止加载进入的文件pollute当前class)
---------------------------------------------------------------------------------------------------------------------------------------------------------

对象与类的总结:(注意事项,ruby会打开已定义的类和模块所以在定义新类名和模块名时切忌避免冲突和混乱)

什么是对象?
对象就是指向类的实例变量,在ruby里面一切皆是对象除了:block,method

什么是类?
类即是Class的实例对象,加上一列实例方法和指向一个superclass
classes,Object,BasicObject,Module...的类都是Class,Class类的类是自己
Class是Molule的子类,所以a class is also a module.
---------------------------------------------------------------------------------------------------------------------------------------------------------

当你include一个module到class或module时ruby会创建一个匿名类包含那个module的内容,
then inserts the anonymous class in the chain,just above the including class itself.
---------------------------------------------------------------------------------------------------------------------------------------------------------
self # => main
self.class # => Object
在ruby的顶层空间是main对象(Object的一个实例),他提供顶层执行环境——>意思时ruby所有操作都是在对象内部执行的。
#补充介绍Kernel
Ruby includes some methods, such as print( ), that you can call from
anywhere in your code. they are actually private instance methods of module Kernel.
class Object includes Kernel, so Kernel gets into every object’s ancestors chain
---------------------------------------------------------------------------------------------------------------------------------------------------------
#令人混淆的self
当前对象-->self:可以理为一个全局变量,在任意时刻只代表一个对象,只有在明确指定方法调用接收者时self才被赋值为该对象.
两种特殊情况:
1.当self的值是main对象时出现class或module定义时self的值会被赋值为定义的class或module对象。
2.在对象A内调用其他对象的方法并返回到A对象后self还是为A对象.
#example:
class C
  def initialize(object)
  #这里的self是c即C的例
    object.methods.grep(/methods$/){
      #这里的self仍然是c因为object在调用methods后返回数据,又回到了c的环境中故self此时表示c
      C.cla_method
    }
  end
  def self.cla_method
  end
end
c = C.new(String)
---------------------------------------------------------------------------------------------------------------------------------------------------------
#动态方法的应用实例:
class Computer
  def initialize(computer_id, data_source)
    @id = computer_id
    @data_source = data_source
    data_source.methods.grep(/^get_(.*)_info$/) { Computer.define_component $1 }
  end

  def self.define_component(name)
    define_method(name) {
    info = @data_source.send "get_#{name}_info" , @id
    price = @data_source.send "get_#{name}_price" , @id
    result = "#{name.capitalize}: #{info} ($#{price})"
    return "* #{result}" if price >= 100
    result
    }
  end
end
#优点:当data_source增加电脑组件时函数能自动识别并为起定义访问器.
---------------------------------------------------------------------------------------------------------------------------------------------------------
#用method_missing作代理:
class Computer
  #to make Computer a blankslate,目的是避免使用method_missing方法代理时与已有方法冲突
  #also can directly inherited from BasicObject to be a blankslate.
  instance_methods.each do |m|
    undef_method m unless m.to_s =~ /^__|method_missing|respond_to?/
  end

  def initialize(computer_id, data_source)
    @id = computer_id
    @data_source = data_source
  end

  def method_missing(name, *args)
    super if !@data_source.respond_to?("get_#{name}_info" )
    info = @data_source.send("get_#{name}_info" , args[0])
    price = @data_source.send("get_#{name}_price" , args[0])
    result = "#{name.to_s.capitalize}: #{info} ($#{price})"
    return "* #{result}" if price >= 100
    result
  end

  #使respond_to?方法正确显示代理是否能接收某个方法。
  def respond_to?(method)
    @data_source.respond_to?("get_#{method}_info" ) || super
  end
end
#该动态代理缺点在于速度慢,可以通过第一次动态创建方法,下一次直接调用定义的方法进行优化(动态定义方法与动态代理的组合)
#example:
def method_missing(name,*args)
  super if !@object.respond_to?(name)
  define_mehtod(name)
    puts "create method #{name} successfully!"
  end
end
---------------------------------------------------------------------------------------------------------------------------------------------------------

局部变量的生命周期:进入其范现生成,离开其范围自动消失。
---------------------------------------------------------------------------------------------------------------------------------------------------------

The code in a class or module definition is executed
immediately. Conversely, the code in a method definition is executed
later, when you eventually call the method.
---------------------------------------------------------------------------------------------------------------------------------------------------------

Scope Wrap-Up
#ruby的scope gates:class,module,def
#Flat Scope:(让变量穿越不同的gate)
my_var = "Success"
MyClass = Class.new do
  puts "#{my_var} in the class definition!"
  define_method :my_method do
    puts "#{my_var} in the method!"
  end
end
MyClass.new.my_method
#output:
⇒ Success in the class definition!
  Success in the method!

#Shared Scope:(在同一个gate内共享变量)
def define_methods
  shared = 0
  Kernel.send :define_method, :counter do
    shared
  end

  Kernel.send :define_method, :inc do |x|
    shared += x
  end
end
define_methods
counter # => 0
inc(4)
counter # => 4

#block的变量范围(ruby1.9以后)
def my_method
  yield(2)
end
x = 1
y = 1
my_method do |x;y|
  #这里的y是声明的块级变量,默认值为nil
  puts "inner block x:#{x}, y:#{y}"
end
puts "outer block x:#{x}, y:#{y}"
#inner block x:2, y:
#outer block x:1, y:1
---------------------------------------------------------------------------------------------------------------------------------------------------------
instance_exec( ) is similar to instance_eval( ), but it also allows you to pass arguments to the block.
---------------------------------------------------------------------------------------------------------------------------------------------------------

#Clean Rooms
提供一个干净区域来执行代码块,主要用于减少冲突
#example:
class CleanRoom
  def complex_calculation
    # ...
  end
  def do_something
    # ...
  end
end

clean_room = CleanRoom.new
clean_room.instance_eval do
  if complex_calculation > 10
    do_something
  end
end
---------------------------------------------------------------------------------------------------------------------------------------------------------

package code:
• In a proc, which is basically a block turned object
• In a lambda, which is a slight variation on a proc
• In a method
#notice: proc and lambda are Proc,Proc is a object,but blocks not.
&res变量放在方法参数最后用以接收代码块,此时res就代表proc
yield 只能回调代码块。
----------------------------------------------------------------------------------------------------------------------------------------------------

block,proc,lambda,mehtod object间的差异:
1.method object 几乎与lambda相同只有一点:lambda执行的范围是定义它时的范围(闭包),Method object是在他所在实例的范围内执行。
#method object的例子:
  #thod_object = Myclass.new.method :my_method
  #method_object.call
2.
---------------------------------------------------------------------------------------------------------------------------------------------------------

keep in mind that a class is just a souped-up module, so anything you
learn about classes also applies to modules.
---------------------------------------------------------------------------------------------------------------------------------------------------------
#***********Import**********
#instance_eval() changes self, and class_eval() changes both self and the current class
#关于instance_eval() 与 class_eval()
1.class_eval顾名思义就是在类环境中执行代码,相当于reopen the class(注:module_eval是其别名,他们只能对class或module使用)
  instance_eval就是在对象中执行代码(注意classes也是对象)
2.若对象使用instance_eval定义方法,那么方法是该对象的singleton_method(若该对象是类那么定义的方法为class_method)
  若类使用class_eval定义方法,那么方法是类的instance_method
---------------------------------------------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------------------------------------------

#关于instance_variable和class_instancece_variable
1.实例变量被存储在实例对象里,只在该对象内共享,不能被该对象的实例或子类使用
2.类也是对象,所以类实例变量只能在类对象内共享
#example:
class MyClass
  @my_var = 1 #class_instance_variable
  def self.read; @my_var; end

  def write; @my_var = 2; end #instance_variable
  def read; @my_var; end
end
obj = MyClass.new
obj.write
obj.read # => 2
MyClass.read # => 1
---------------------------------------------------------------------------------------------------------------------------------------------------------

#@@v被定义在main对象的环境中,main是Object类的实例,然而MyClass是Ojcect的子类
#所以MyClass继承了class_variable @vv,故最后结果是2
@@v = 1
class MyClass
  @@v = 2
end
@@v # => 2
---------------------------------------------------------------------------------------------------------------------------------------------------------

Class#new( ) also accepts an argument (the superclass of thenew class)
and a block that is evaluated in the context of the newborn class:
#example:
c = Class.new(Array) do
  def my_method
    'Hello!'
  end
end
---------------------------------------------------------------------------------------------------------------------------------------------------------

类方法就是类的singleton方法
#def obj.a_singleton_method; end
#def MyClass.another_class_method; end
---------------------------------------------------------------------------------------------------------------------------------------------------------
#当一个类在被其他类调用时怎么进行重构?
class Book
  def title # ...

  def subtitle # ...

  def lend_to(user)
    puts "Lending to #{user}"
  # ...

  def self.deprecate(old_method, new_method)
    define_method(old_method) do |*args, &block|
      warn "Warning: #{old_method}() is deprecated. Use #{new_method}()."
      send(new_method, *args, &block)
    end
  end

  deprecate :GetTitle, :title
  deprecate :LEND_TO_USER, :lend_to
  deprecate :title2, :subtitle
end
#b = Book.new
#b.LEND_TO_USER("Bill" )
#⇒ Warning: LEND_TO_USER() is deprecated. Use lend_to().
# Lending to Bill
---------------------------------------------------------------------------------------------------------------------------------------------------------

#eigenclass只有一个实例且不能被继承,对象的singleton方法就放在eigenclass里面。
#singleton method
def obj.my_singleton_method; end
eigenclass.instance_methods.grep(/my_/) # => ["my_singleton_method"]

#class mehtod
class MyClass
  def self.my_method; end
end
def MyClass.my_other_method; end

class MyClass
  class << self
    def my_method; end
  end
end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值