中成网站建设
    成都做网站,就选中成网站建设!专业四川网站建设,成都网站建设服务提供商
            企业宣传网站建设、电子商务网站建设、OA办公系统。联系电话:028-66165255
    资讯列表  
 ASP.NET防止用户多次登录的方法…
 生成不重复的随机整数
 ASP.NET获取IP的6种方法
 ASP dot net 里的状态管理-Ses…
 判断获取的参数是否为null
 中文验证码生成实例
 微软发布第二个实验版的.Net 4…
 微软轻量级Web开发平台WebMatr…
 asp.net 生成图片验证码
 Asp.net直接保存文件到客户端
 .Net开发中的多线程编程总结
 C#中关于get和set的详细例子介…
 ASP.NET编程技巧:提高asp.net…
 asp.net 剪切 缩小图片原码
 截断过长字符串为省略号算法
    资讯详情  
牛人点评Ruby语言十大令人喜爱的特点
发布时间:2009-08-31                  来源:成都网站建设--中成网建         【加入收藏】

我每天都要用 Ruby 工作,久而久之,我现在真的喜欢上使用它了。(51CTO编者注:本文作者Yehuda Katz是Ruby on Rails核心开发团队的成员,以及Merb项目的主要推动者。)下面是一个列表,列出了我最喜欢的 Ruby 语言特点。一些特点显而易见,一些特点也存在于其他语言中。分享 Ruby 这些我喜欢的特点,并非是为了和其他语言进行比较和对比。

1. 动态类型

静态类型语言也有很不错的功能,比如编译时验证和 IDE 支持。不过根据我的经验,动态类型对于项目启动真的有很大帮助,并且便于进行更改,尤其是在项目的早期到中期这些阶段。

为了能够让我能够轻松地继续对象交换,我不需要为新对象创建正式的接口,这点让人很开心。

2. Duck Typing(鸭子类型)

这只是动态类型的一个有效的扩展。在 Ruby 中,预期能够对字符串对象进行操作的方法并不会检查 is_a?(String)。它们检查对象是否 respond_to?(:to_str),如果是,就接着调用对象的 to_str。与此类似,在 Ruby 中表示路径(Path)的对象能够实现一个 to_path 方法为提供路径重现(representation)。

在 Rails 语言中,对于具有“模型”特性的对象,我们可以使用这样的技巧来实现对它们 respond_to?(:to_model) 的预期。如果这些对象能够为我们提供一个它们自身的“模型”重现,我们就能够在相关语境中支持任何类型。51CTO之前曾发布过有关Ruby中鸭子类型的介绍,可以参考一二。

3. 令人叹为观止的模块

Ruby 提供了一个与 Scala、Squeak 和 Perl 语言中“traits”类似的功能。事实上,Ruby 模块可以在运行时动态地址类等级中添加新元素。运行时可以动态地对 super 的使用继续评估以考虑所有添加的模块,这样就可以方便地按照所需多次地扩展超类功能,而且无需指定在类声明时确定super的加载地点。

此外,Ruby 模块提供了生命周期钩子(hook)append_features 和 included,这样就可以使用模块来互相隔离扩展以及在特性包含的基础上动态的扩展类。

4. 类主体不是专用的

在 Ruby 中,类主体不是专用的语境。它们仅仅是一个对象类的自身指向点。如果你用过 Rails,你可能看到这样的代码:

  1. class Comment < ActiveRecord::Base  
  2.   validates_presence_of :post_id 
  3. end 

validates_presence_of 看起来好像是语言的一项功能,但实际上它是 Comment 上调用的方法,而 Comment 由 ActiveRecord::Base 提供。

该方法可以类中的执行任意代码(arbitrary code),包括创建新的方法,执行代码中其他内容,或者更新类实例变量。与必须在编译时运行的 Java 标注不同,Ruby 类主体能够考虑到运行时的信息,如动态提供的选项或其他代码的评估结果。

5. 字符串求值(eval 功能)

这可能是一个不同的想法。这里我不是指任意运行时字符串的求值,而是用于在 Ruby 程序启动过程中创建方法的字符串求值。

这样就能够利用 Ruby 定义的结构(如 Rails 路径或 AOP 定义),并且能够将其编译到 Ruby 方法中。当然,也可以将其作为其他语言的附件(add-on)来实现,但在纯 Ruby 环境中实现这类功能是可能的。在很大程度上,它是一种自足执行(self-hosting)的一种语言。

6. 区块和 Lambda 表达式

我已经说过多次,这里再重复一次:我认为没有匿名 lambda 表达式的语言还没有足够强大到让我每天使用它。这些构造事实上非常常见,在 Ruby、JavaScript、Scala、Clojure 和 Lisp 中也存在。51CTO之前介绍过Ruby 1.9中的Lambda表达式,有兴趣的读者可以看看。

利用它们,就能够实现看起来好像是语言功能的区块范围内的构造。最常见的使用示例是对文件的操作。在没有 lambda 的语言中,用户不得不在同一个语法范围(和他们最初打开的文件一致)中使用一段“确保”区块,以确保关闭了资源。

在 Java 中:

  1. static void run(String in)   
  2. throws FileNotFoundException {  
  3.   File input = new File(in);  
  4.   String line; Scanner reader = null;  
  5.   try {  
  6.     reader = new Scanner(input);  
  7.     while(reader.hasNextLine()) {  
  8.       System.out.println(reader.nextLine());  
  9.     }  
  10.   } finally { reader.close(); }  

 

Java 版的代码常常需要在 try 区块中包括 Scanner 的创建以保证其关闭。相反,让我们看看 Ruby 的代码:

  1. def run(input)  
  2.   File.open(input, "r"do |f|  
  3.     f.each_line {|line| puts line }  
  4.   end 
  5. end 

 

由于区块的存在,我们可以省去在单个位置关闭文件的麻烦,将程序员错误减少到最小并且能够减少重复。

7. 功能组合:自足执行(self-hosting)语言

以上特点组合组合在一起,让我们能够在 Rails 中“扩展”Ruby 语言。看下面这段代码:

  1. respond_to do |format|  
  2.   if @user.save  
  3.     flash[:notice] = 'User was successfully created.' 
  4.     format.html { redirect_to(@user) }  
  5.     format.xml { render :xml => @user:status =>ted, :location => @user }  
  6.   else 
  7.     format.html { render :action => "new" }  
  8.     format.xml { render :xml => @user.errors, :status => :unprocessable_entity }  
  9.   end 
  10. end 

 

在这个示例中,我们可以无缝地将方法(respond_to)与正常的 Ruby 代码(if 和 else))混合在一起,以生成一个新的区块范围的构造。Ruby 的区块语法让我们能够在区块内使用 return 和 yield,从而进一步混合代码区块与语言构造(如 if 或while 的界限)。

在 Rails 3 中,我们引入下面一段代码:

  1. class PeopleController < ApplicationController  
  2.   respond_to :html:xml:json 
  3.    
  4.   def index  
  5.     @people = Person.find(:all)  
  6.     respond_with(@people)  
  7.   end 
  8. end 

 

这里,我们在类中提供 respond_to。它告诉 Rails:respond_with(在 index 中)应接收 HTML、XML、或 JSON 作为响应格式。如果用户请求不同的格式,我们将自动返回一个 406 错误(Not Acceptable)。

如果再稍微深入挖掘一下,你会看到 respond_to 方法被定义为:

  1. def respond_to(*mimes)  
  2.   options = mimes.extract_options!  
  3.    
  4.   only_actions   = Array(options.delete(:only))  
  5.   except_actions = Array(options.delete(:except))  
  6.    
  7.   mimes.each do |mime|  
  8.     mime = mime.to_sym  
  9.     mimes_for_respond_to[mime]          = {}  
  10.     mimes_for_respond_to[mime][:only]   = only_actions   unless only_actions.empty?  
  11.     mimes_for_respond_to[mime][:except] = except_actions unless except_actions.empty?  
  12.   end 
  13. end 

 

这个方法在 ActionController::MimeResponds::ClassMethods 模块上定义,而该模块属于 ActionController::Base。此外,在该模块的生命周期钩子 included 中使用 class_inheritable_reader 定义了 mimes_for_respond_to。class_inheritable_reader method (macro?)。 使用 class_eval 将方法添加到正在使用的类上,以模拟内置的 attr_accessor 功能。

是否理解所有这些细节无关紧要。重要的是利用上述的 Ruby 功能,我们就可以创建抽象层,从而能够为 Ruby 语言添加新的特性。

开发者看到 ActionController::MimeResponds,他无需去了解 class_inheritable_reader 如何运行——他只需了解这个基本功能。而看到 API 文档的开发者也无需了解 class-levelrespond_to 如何运行——他只需了解这个已经提供的功能。

这样,剥离每一层就可以在其他抽象上构造一个简单的抽象。没有必要一次剥离所有抽象层。

8. 很好的字面含义

在使用 Ruby 编程时,我常常会忘记这一点;只有在使用一些字面意义很少或表达很差的语言时,我才会体会到 Ruby 的这一优点。

Ruby 中每个词都具有很好的字面意义:

  1. 字符串:single-line、double-line、interpolated
  2. 数字: binary、octal、decimal、hex
  3. 空值:nil
  4. 布尔玛:true、false
  5. 数组: [1,2], %w(每个字都是元素)
  6. 哈希表(Hash): {key => value} 和{key: value}(Ruby 1.9)
  7. 正则表达式:/hello/、%r{hello/path}、%r{hello#{interpolated}}
  8. 符号::name 和 :”weird string”
  9. 区块:{ 区块文字 }

我想我可能会漏掉一些。虽然有些学术性,但可读性良好的语句的确能够增强开发者的编码能力,让他们写出简短而极具表达性的代码。

当然,通过对新的 Hash 对象实例化并一个一个地输入关键字和值,你也可以实现 Hash 的功能。但这减少了 Hash 的用途,比如作为方法参数。

Hash 字面上的简洁性让 Ruby 程序员能够无需经过语言设计者的许可就能够添加限制性关键字参数。这也是自足执行的又一个实例。

9. 所有事物都是对象,所有代码都是可执行的并具有 self

很大程度上,类主体之所以能够按照这样的方式运行,是 Ruby 语言始终如一地面向对象的结果。在类主体内部,Ruby 仅执行具有指向类的 self 的代码。此外,类内容中没有什么是专用的;可以在任何位置对类语境中的代码进行求值。

比如:

  1. module Util  
  2.   def self.evaluate(klass)  
  3.     klass.class_eval do 
  4.       def hello  
  5.         puts "#{self} says Hello!"   
  6.       end 
  7.     end 
  8.   end 
  9. end 
  10.    
  11. class PersonName < String 
  12.   Util.evaluate(self)  
  13. end 

 

这完全等同于:

  1. class PersonName < String 
  2.   def hello  
  3.     puts "#{self} says Hello!"   
  4.   end 
  5. end 

 

Ruby 移除了不同位置代码之间的人工界限,降低了创建抽象的概念上的成本。这是强大的、始终如一的对象建模的结果。

有关该主体,再提供一个示例。Ruby 常见的术语:possibly_nil && possibly_nil.method_name。由于 nil 只是 Ruby 的一个对象,向它发送一个它无法理解的信息,会造成一个 NoMethodError 错误。有些开发者建议使用这种句法:possibly_nil.try(:method_name)。可以在 Ruby 中通过以下代码来实现:

  1. class Object 
  2.   alias_method :try, :__send__  
  3. end 
  4.    
  5. class NilClass 
  6.   def try  
  7.     nil 
  8.   end 
  9. end 

 

本质上,这将为每个对象添加方法 try。当 Object 是 nil 时,try 只返回 nil。但 Object 不是 nil 时,try 就调用当前所用的方法。

使用 Ruby 开放类的目标程序,结合 Ruby 中所有事物都是对象(包括 nil)这一事实,我们就能够创建新的 Ruby 功能。同样,这没有什么大不了的,不过是又一个示例:在语言中做出正确的选择,我们就能够创建有用的抽象。

 

 

 

 
上一篇:存储的GB如何定义?苹果站到厂商一侧
下一篇:构建高性能Web站点--使用负载均衡
【打印】    【关闭】    【字体变小】    【字体变大】

友情链接

首页  |  建站学院  |  网站建设  |  成功案例  |  业务体系  |  软件定制  |  解决方案  |  联系我们  |  免责声明
中成网建公司地址:四川省成都市双楠双安东巷1号18-3-5 电话:028-6616 5255 版权所有 @ 中成网建
成都网站建设网址:www.csccd.net www.csccd.cn 邮箱:web#csccd.net
信息产业部备案号:蜀ICP备08106559号