Ruby元编程

  • 方法
  • 代码块
  • 类宏
  • Eval方法

实例变量、方法、类

实例变量(Instance Variables)是当你使用它们时,才会被建立的对象。因此,即使是同一个类的实例,也可以有不同的实例变量。

从技术层面上来看,一个对象(实例)只是存储了它的实例变量和其所属类的引用。因此,一个对象的实例变量仅存在于对象中,方法(我们称之为实例方法(Instance Methods))则存在于对象所属的类中。这也就是为什么同一个类的实例都共享类中的方法,却不能共享实例变量的原因了。

  • 类也是对象。
  • 因为类也是一个对象,能应用于对象的皆可运用于类。类和任何对象一样,有它们自己的类,Class类即是Class类的实例。
  • 与其它的对象一样,类也有方法。对象的方法即是其所属类的实例方法。亦即,任何一个类的方法就是Class类的实例方法。
  • 所有的类有共同的祖先Object类(都是从Object类直接或间接继承而来),而Object类又继承自BasicObject类,Ruby类的根本。
  • 类名是常量(Constant)。
  n = Class.new
  puts n.ancestors
  puts n.supperclass
  puts n.supperclass.supperclass
  puts n.supperclass.supperclass.supperclass

打开类

其实这个就跟方法重定义是一样的结果,不过随意改动可能会产生严重的后果,比如说你改的这个方法在其它地方有使用到,所以这种方法还是慎用,除非你非常明确该方法不会造成其它后果。

puts 'abc'.replace('a') # a
class String
  def replace(string)
    puts '重新打开了类'
  end
end
'abc'.replace('a')  #'重新打开了类'

我们也可以使用细化来实现这个过程

细化

module StringExtensions
  refine String do
    def replace(string)
       puts '细化'
    end
  end
end

在需要使用这个方法的地方使用using

如:using StringExtensions
细化的好处就是不会全局影响,在你需要使用的地方using就可以了,风险相对较小。

调用方法

类中的方法是怎么调用的?

  • 方法的查找(接收者和祖先链)
    Ruby中要在类中查找一个方法,首先在它的类查找这个方法,如果没有,则往上查找,如此类推,直到祖先链的顶端,到最后,如果还没找到,会抛出method_missing异常。如果有了解过JS,那么你肯定非常明白这个过程,因为JS中的方法查找也是类似于这个过程。
  • 执行方法
    在执行方法的过程中,Ruby始终需要一个接收者的引用,也就是self

self关键字

任何时刻,Ruby中只有一个对象能充当当前对象,并且没有哪个对象能长期充当这个角色,调用一个方法时,接收者就成为了self,从这一刻起,所有的实例变量都是self的实例变量,所有没有明确指明接收者的方法都在self上调用。
举个栗子:

class Book
  def get_library
    @book_count = 1000
    self
  end

  def self.is_my_book?(book)
    false
  end
end
b = Book.new
b.get_library # 这个时候,b就充当了self
b.is_my_book?('Ruby元编程') # undefined method `is_book?' for #<Book:0x00000002b92268 @library=1000> (NoMethodError)
Book.is_my_book?('Ruby元编程') # false

上面调用is_my_book?的方法为什么会报错?
那是因为 self.is_my_book?(book) 等于 Book.is_my_book?(book)
当b调用的时候,self引用b实例对象,不等于Book,所以就会抛出找不到方法的错误

方法

  • 动态派发(调用方法:对象.send(方法名,参数))
class Book
  def create_book
    'Ruby元编程'  
  end  
  
  def update_book  
    'Ruby元编程'  
  end  
  
  def delete_book
    'Ruby元编程'    
  end  

  def search_book
    'Ruby元编程'  
  end
end  
  
s = Book.new  
  
puts s.send(:get_one_name)   
puts s.send(:get_two_name)  
puts s.send(:get_three_name) 
puts s.send(:get_four_name)  
  • 动态定义
class Book
  ['create', 'update', 'delete', 'search'].each do |item|
    define_method("#{item}_book"){
      puts "#{item}-Ruby元编程"
    }
  end
end
b = Book.new
b.create_book # create-Ruby元编程
b.update_book # update-Ruby元编程
b.delete_book # delete-Ruby元编程
b.search_book # search-Ruby元编程
  • method_missing(幽灵方法)
# encoding: utf-8
class Book
  def method_missing(name, *argc)
    if [:create_book, :update_book, :delete_book, :search_book].include?(name)  
      puts "#{name}-Ruby元编程" 
    else
      super  
    end
  end
end
b = Book.new
b.create_book# create-Ruby元编程
b.update_book# update-Ruby元编程
b.delete_book # delete-Ruby元编程
b.search_book# search-Ruby元编程
b.book # undefined method `book'

代码块

...

类宏

如果按照以前的做法,定义一个属性的读写必须将每个属性定义一个Get 和 Set方法,比如如下代码

class Post
  def title=(title)
    @title = title
  end
  def title
    @title
  end
 ....
 ....

如果像一篇文章这样,定义title,content,author等属性,就需要写3组这样的方法,非常不方便。这个时候,就要亮出Ruby的类宏attr_accessor(module的类里面的一个C语言写的方法,附上超链接,以上代码就可以写成

  class Post
    attr_accessor :title
  end

Eval方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,154评论 5 464
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,252评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,107评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,985评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,905评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,256评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,978评论 3 388
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,611评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,891评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,910评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,736评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,516评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,995评论 3 301
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,132评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,447评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,034评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,242评论 2 339

推荐阅读更多精彩内容