Ruby知识积累2
来源:互联网 发布:淘宝子账号登陆不了 编辑:程序博客网 时间:2024/05/17 03:00
- Block:
Proc.new my_proc = Proc.new { puts "tweet" } my_proc.call lambda my_proc = lambda { puts "tweet" } my_proc.call -> my_proc = -> { puts "tweet" } my_proc.call Parameter: e.g. class Tweet def post(success, error) if authenticate?(@user, @password) success.call else error.call end end end tweet = Tweet.new('Ruby Bits!') success = -> { puts "Sent!" } error = -> { raise 'Auth Error' } tweet.post(success, error) e.g. tweets = ["First tweet", "Second tweet"] printer = lambda { |tweet| puts tweet } tweets.each(&printer) # &操作符将lambda转换为block block_given? e.g. class Timeline attr_accessor :tweets def print if block_given? tweets.each { |tweet| puts yield tweet } else puts tweets.join(', ') end end end timeline = Timeline.new timeline.tweets = ["One", "Two"] timeline.print timeline.print { |tweet| "tweet: #{tweet}" } e.g. class Tweet def initialize yield self if block_given? end end Tweet.new do |tweet| tweet.status = "Set in initialize!" tweet.created_at = Time.now end closure(闭包): def tweet_as(user) lambda { |tweet| puts "#{user}: #{tweet}" } end gregg_tweet = tweet_as("andy") greeg_tweet.call("Mind blowing!") Symbol#to_proc tweets.map { |e| tweet.user } tweets.map(&:user)
- Struct:
e.g. 类: class Tweet attr_accessor :user, :status def initialize(user, status) @user, @status = user, status end def to_s "#{user}: #{status}" end end 结构体: Tweet = Struct.new(:user, :status) do def to_s "#{user}: #{status}" end end
- Alias_method:
Bad: class Timeline def initialize(tweets = []) @tweets = tweets end def tweets @tweets end def contents @tweets end end Good: class Timeline def initialize(tweets = []) @tweets = tweets end attr_reader :tweets alias_method :contents, :tweets end
- Define_method:
e.g. native: class Tweet def draft @status = :draft end def posted @status = :posted end def deleted @status = :deleted end end change: class Tweet status = [:draft, :posted, :deleted] status.each do |status| define_method status do @status = status end end end
- Send:(常用于访问protected和private方法)
e.g. class Timeline def initialize(tweets) @tweets = tweets end def contents @tweets end private def direct_message #... end end tweets = ['Compiling!', 'Bundling...'] timeline = Timeline.new(tweets) timeline.contents timeline.send(:contents) timeline.send("contents") timeline.send(:direct_message) timeline.public_send("direct_message") # only can access public methods
- Method:
e.g. class Timeline def initialize(tweets) @tweets = tweets end def contents @tweets end def show_tweet(index) puts @tweets[index] end end tweets = ['Compiling!', 'Bundling...'] timeline = Timeline.new(tweets) content_method = timeline.method(:contents) content_method.call show_tweet = timeline.method(:show_tweet) show_tweet.call(0) (0..1).each(&show_tweet) #相当于show_tweet(0)和show_tweet(1)
- Self:
e.g. puts "Outside the class: #{self}" # main class Tweet puts "Inside the class: #{self}" # Tweet def self.find(keyword) # ... end end
- Class_eval(在指定类中执行):
e.g. class Tweet attr_accessor :status attr_reader :created_at def initialize(status) @status = status @created_at = Time.now end end Tweet.class_eval do attr_accessor :user end tweet = Tweet.new("Learning class_eval") tweet.user = "doit"
- Create a log_method:
log_method以类名和方法名作为参数,调用class_eval来执行类中的代码。使用alias_method来保存原先的方法,使用define_method来重定义方法,对该方法的调用过程进行记录,使用send来调用原先的方法。 class MethodLogger def log_method(klass, method_name) klass.class_eval do alias_method "#{method_name}_original", method_name define_method method_name do |*args, &block| puts "#{Time.now}: Called #{method_name}" send "#{method_name}_original", *args, &block end end end end e.g. class Tweet def say_hi puts "hi" end end logger = MethodLogger.new logger.log_method(Tweet, :say_hi) Tweet.new.say_hi
- Instance_eval:
e.g. class Tweet attr_accessor :user, :status end tweet = Tweet.new tweet.instance_eval do self.status = "Changing the tweet's status" end Good: class Tweet attr_accessor :user, :status def initialize yield self if block_given? end end Tweet.new do |tweet| tweet.status = "I was set in the initialize block!" tweet.user = "Gregg" end Better: class Tweet attr_accessor :user, :status def initialize(&block) instance_eval(&block) if block_given? end end
- Method_missing:
当无法找到方法时调用 e.g. class Tweet def method_missing(method_name, *args) logger.warn "You tried to call #{method_name} with these arguments: #{args}" super # ruby's default method handling raise a NoMethodError end end e.g.(对一些方法进行委托) class Tweet DELEGATED_METHODS = [:username, :avatar] def initialize(user) @user = user end def method_missing(method_name, *args) if DELEGATED_METHODS.include?(method_name) @user.send(method_name, *args) else super end end end e.g.(将未知方法,全部委托到user) require 'delegate' class Tweet < SimpleDelegator def initialize(user) super(user) end end e.g. class Tweet def initialize(text) @text = text end def to_s @text end def method_missing(method_name, *args) match = method_name.to_s.match(/^hash_(\w+)/) if match @text << " #" + match[1] else super end end end e.g.(define_method) class Tweet def initialize(text) @text = text end def to_s @text end def method_missing(method_name, *args) match = method_name.to_s.match(/^hash_(\w+)/) if match self.class.class_eval do define_method(method_name) do @text << " #" + match[1] end end send(method_name) else super end end end
- Response_to?:
e.g. class Tweet ... def respond_to?(method_name) method_name =~ /^hash_\w+/ ||super end end tweet = Tweet.new tweet.respond_to?(:to_s) tweet.respond_to?(:hash_ruby) tweet.method(:hash_ruby) # NameError:undefined method
- Response_to_missing?:(Ruby 1.9.3)
e.g. class Tweet ... def respond_to_missing?(method_name) method_name =~ /^hash_\w+/ ||super end end tweet = Tweet.new tweet.method(:hash_ruby) # return a Method object
- Implement a simple DSL:
DSL:领域专用语言 e.g. class Tweet def initialize(user) @user = user @tweets = [] @annotations = {} end def submit_to_twitter tweet_text = @tweet.join(' ') if tweet_text.length <= 140 puts "#{@user}: #{tweet_text}" puts @annotations.inspect unless @annotations.empty? else raise "your tweet is too long." end end def text(str) @tweet << str self end def mention(*users) users.each do |user| @tweet << "@" + user end self end def hashtag(str) @tweet << "#" + str self end def link(str) @tweet << str end def method_missing(method, *args) @annotations[method] = args.join(', ') end end def tweet_as(user, text=nil,&block) tweet = Tweet.new(user) tweet.text(text) if text tweet.instance_eval(&block) if block_given? tweet.submit_to_twitter end tweet_as 'marken' do mention 'china','usa' text('I made a DSL!').hashtag('hooray').hashtag('ruby') link 'http://www.somewhere.com' end
0 0
- Ruby知识积累2
- Ruby语言知识积累
- Ruby知识积累1
- 小知识积累(2)
- 知识积累2……
- 知识积累
- 知识积累
- 知识积累
- 知识积累
- 知识积累。。
- 知识积累
- 知识积累
- 知识积累
- 知识积累
- 知识积累
- 知识积累
- 知识积累
- 知识积累
- Person p=new Person()的感悟
- Ubuntu常用软件推荐,图文详细说明及下载
- Combination Sum
- JAVA程序在eclipse下可运行但不能在cmd命令下运行的原因
- Java Android客户端开发
- Ruby知识积累2
- Codeforces Round #254 (Div. 2):A. DZY Loves Chessboard
- python中json.dumps使用及字符编码
- Win7服务对照表
- Codeforces Round #246 (Div. 2):A. Choosing Teams
- 風雷益
- 设置启动MyEclipse8.5的时候选择工作空间
- Ubuntu命令行下安装、卸载、管理软件包的方法
- Codeforces Round #246 (Div. 2):B. Football Kit