科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道Java世界的Ruby(2)

Java世界的Ruby(2)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

这篇文章,我希望能够和你一起分享我在开发Java系统的时候使用Ruby的那种兴奋感。我比较一下Java和Ruby的优点和缺点,而且介绍一下JRuby解释器的支持者和反对者...

作者:silentbalanceyh 来源:IT专家网 2008年5月6日

关键字: RUBY 世界 java

  • 评论
  • 分享微博
  • 分享邮件
功能性编程

  Ruby支持熟练的多样化设计程序范例。另外的对于它的纯面向对象的风格,它同样支持一次性脚本的程序化风格:你可以在类和函数外任何地方写代码,就像函数在任何类之外一样。

  更有趣的是,对于Java程序员寻找的新的和有用的观点,Ruby支持功能范例。你可以在Java里面使用更多的功能程序结构,使用很多类库支持就像Jakarta Commons Collections系列的集合包一样,但是这些语法是笨拙的。Ruby,虽然不是一种纯功能性语言,但是对待功能和匿名块如同完整的语言成员一样,这些都是能够像其他简单对象一样被传递到周围和利用的。

  在Java里面,你经常反复使用集合的Iterator(迭代器),从逻辑上去遍历集合里面的每一个元素。但是这种遍历仅仅是这样一个细节实现:一般来说,你仅仅尝试去接受对集合里面的每一个元素采取同样的逻辑。在Ruby里,你可以将一段代码块传给一个执行它的方法,遍历是在执行后台运行的。例如,[1,2,3,4,5].each{|n|print n*n, “ “}将打印这样的字符串:1 4 9 16 25;迭代器将会遍历这个列表里面的每一个元素将他作为一个变量n传到代码块里面。

  利用在代码块之前和之后执行的指令将代码块封装起来的功能程序是很有用的。比如,在Java里面,你可以使用Command模式保证一个文件的打开和关闭、数据库的事务处理、或者其他的资源调用。这些匿名内部类和回调函数式的无用框架将会使代码变得冗余沉重;除此之外,这里还有一个变迁规则就是变量在匿名Command类里面传递的时候必须定义成为final。而且为了确保最后的代码块在逻辑上能够执行,整个工作就会使用try{…}finally{…}封装起来。

  在Ruby里面,你可以封装任何函数或者代码块,不需要任何方法定义或者匿名内部类。在Listing 2里面,这个文件打开,然后在write()方法执行过后关闭。没有任何需要使用transaction()方法的代码和代码块。

  Listing 2. Wrap a code block

File.open("out.txt", "a") {|f|
    f.write("Hello")
}

  元程序语言

  你一般情况下是定义你的Java类作为你的源程序,但是你仍然可以在运行时进行类定义的操作。这个需要高级技术比如在加载类的时候增加字节码。比如,Hibernate直接插入数据存取逻辑到商业对象的字节码里面,从额外的数据存取层里保存应用程序。但是类操作,又称为元程序,在实践中仅仅是用来组织基础程序的:应用程序是不能有效地引入这些技巧和脆弱的技术的。

  即使在开发的时候,Java限制了开发者改变类的能力。为了加入一个isBlack()方法检测一个String是否全是空字符串,你不得不加入一个带有静态方法的StringUtils 类;理论上,这个新方法是输入String的。

另一方面,如何在Ruby里简单地用一个空白来扩展String类?方法。实际上,因为在Ruby里面任何东西都是一个对象,你能够增加Fixnum类,这个等价于Java里面的原始int类型,如同Listing3所表示的:

  Listing 3. Add method to built-in classes String and Fixnum

class String
    # Returns true if string is all white space.
    # The question mark indicates a Boolean return value.
    def blank?()
        !(self = /\S/)
    end
endclass Fixnum
# Returns 0 or 1 which in Ruby are treated as false and true respectively.
    def odd?()
    return self % 2
    end
endputs " ".blank? # true
# The next line evaluates if-then similarly to Java's ternary operator ?:
puts (if 23.odd? then "23 odd" else "23 even" end)

  JRuby:Java里的Ruby

  作为一个Java程序员,你不要想在产品中使用Ruby直到你能够让它和存在的Java应用程序和类库进行交互,而这些程序和类库之中能够支持Ruby的很多种类的基本功能。JRuby,JVM下的一个开源Ruby解释器,能够在Java里面使用Ruby类库。就像标准的Ruby解释器一样,除开使用Ruby调用本地方法(C代码)或者Java类库以外,Ruby代码都能够在JRuby里面正确执行。

  相比较于微软的.NET平台的公共语言运行时,JVM往往只能够支持一种语言。但是事实上,JVM平台不仅仅能够支持Java,而且可以支持Python、JavaScript、Groovy、Scheme,和其他各种语言,这意味着有必要的时候,Ruby代码能够和这些语言很好地进行交互。

  在2006年7月中旬,JRuby仅仅有一个预览版本(0.9)。但是它迅速发展起来:一个志愿者团队从2005年一月开始总共发布了五个版本。JRuby通过针对标准解释器的不断评估测试逐渐成熟起来,而且现在已经超过90%的测试都是在基本支持Ruby on Rails这个框架。

  为了尝试JRuby,保证Java SE 5 是安装好了的而且JAVA_HOME环境变量也是设置好了的。从JRuby的工程页面下载压缩包然后解压。设置JRUBY_HOME环境变量到JRuby安装的根目录。你可以在bin目录里面尝试着用jirb进行交互。大多数场合,你将使用JRuby解释器——创建一个文件将文件名作为一个参数传递到JRuby的bin目录下批处理脚本。

  除了执行先前的Ruby代码,你仍然可以使用JRuby来构造Java对象,调用Java方法,从一个Java类继承。一个Ruby类能够实现Java接口——有必要的话可以在Java里面静态调用Ruby方法。

  为了从Ruby访问Java需要初始化类库,需要以”java”命令开始。接下来用include_class方法指定需要使用的Java类,比如,include_class “javax.jms.Session”。你能够使用include_package导入整个Java包到Ruby模块里面。就像Java导入包的通配符语句一样,尽量避免include_package使用产生的名称冲突是明智的;在JRuby里,如果解释器为了需要的类搜索所有的包也是格外不明智的。尽可能严格地使用include_class。

很多Java标准类的名称和Ruby类的名称相同。为了解决这样的冲突,传递一个代码块到include_class函数,为这个Java类返回一个新名称,而且JRuby将使用这个名称作为Java类的别名。(见Listing4)

  Listing 4. Include a Java class with clashing name

require "java"
# The next line exposes Java's String as JString
include_class("java.lang.String") { |pkg, name| "J" + name }
s = JString.new("f")

  或者,你可以创建一个包含java类定义的Ruby模块,但是需要在一个隔离的名称空间里面。例如:

  Listing 5. Java module importing multiple Java classes

require "java"
module JavaLang
    include_package "java.lang"
ends = JavaLang::String.new("a")

  JRuby的好处是什么?

  像Ruby一样的动态语言经常使用在专业领域就像整合其他系统一样;JRuby在Java里面扮演了这个角色。比如,JRuby能够从一个系统读出数据,将这个数据传递插入到另外一个系统里。当需求改变的时候,修改一段JRuby脚本相对于修改配置文件来说简单得多,所以避免了Java综合代码里面复杂的编译和发布周期。

  除开在Ruby里使用Java,你也可以从在Java里使用Ruby,让你的应用程序容易编写。利用JRuby的最小化构造语句方法,你可以创建更加容易使用的专业领域语言供用户工作。比如,一个赌博引擎的脚本系统能够引入Ruby类来描述字符,媒介和其他游戏实体。

  此为,使用Ruby的动态机制,用户能够改变脚本类的定义。这些Ruby对象允许直接使用方法管理它的状态和行为。另外一方面,一般使用用户配置好的键值通过Java映射传递,削弱了对象的功能完整性。

  Ruby脚本有点像加速过的配置文件。一般Java应用程序的配置都是使用xml文件或者属性文件,但是这些对于参数定义在开发时间上受到了一定限制。使用Ruby脚本能够使你的系统要么从一个文本要么从一个内置编辑器里面读取,用户能够自由自定义行为无论什么情况只要你想放置脚本。这样的方法,Ruby使用行为结合配置,提供了Java插件API的功能,而且不需要JavaIDE或者编译器,节省了构建和发布jar文件的步骤。

  例如,一个用户提供的脚本能够嵌入到一个应用程序事件管理里面用来对确认的可疑条件进行过滤,然后将发送一个通知给系统管理员以及在一个特定的安全发行数据库里面记入日志,或者启动脚本能够清除旧文件以及支配用户数据存储。同样的很多富客户端允许用户改变菜单和工具条的位置——使用Ruby嵌入,一个用户的新菜单可以触发任何用户想要的行为。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章