`
Eastsun
  • 浏览: 304530 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

Java.next:第一部分——共同点

阅读更多
  原文地址Java.next: Common Ground
  翻  译Eastsun
  本文是Java.next系列的第一部分。在这一部分,我将探讨作为Java.next的语言所具有的共同特征。
  我选择了四种语言作为“Java.next”的代表:Clojure,Groovy,JRuby,以及Scala。乍看起来,这几种语言有着很大的不同。Clojure是Lisp方言;Groovy是作为“类Java”的选择;JRuby即具有Ruby语言的优雅,同时也有着Rails所带来的优势;与其他都不一样的是Scala,它有着静态语言所具有的特点。
  正如你所料想的一样,有很多关于这些语言中谁才是最好的辩论。之所以有着这么多的辩论,很大程度上是因为这些语言有着很多共同点。它们有着一个共同的演变背景:Java语言。Java语言所具有的优点以及缺陷影响着这些语言的设计方向。
  在这篇文章中,我着重从下面两个方面来阐述这些语言的共同点:

  ☆ 过去的10年中,我们在基于虚拟机、面向对象的语言编程中得到了很多关于如何开发易读的、可维护的应用。Java.next吸取了这些成果,使得这些语言更注重于问题的本质而不是形式。
  ☆ “本质 VS 形式”的设计理念使得编程方式发生了很大的改变,这种观念的变化比以前从C/C++到Java的转变更大。


  我将Java.next所具有的共同优点概括为以下八点:
  ● 一切皆对象
  ● 简洁的属性定义方式
  ● 易用的集合类
  ● 函数式编程
  ● 运算符重载
  ● 可维护的异常处理
  ● 给已有类增加新方法
  ● 创建新的语言结构



一切皆对象
  在Java中,我们每时每刻都要面对对象类型与基本类型的不同之处。这种不同导致三个实际问题:
  1.API必须写两份:一个针对对象类型;一个针对基本类型。更糟糕的情形是需要重写多份:一个针对对象类型,然后对每一个基本类型各写一份。
  2.默认的数值类型有着范围限制,一旦越界,程序会以诡异的形式中断。
  3.对于那些高精度类型(译者注:指BigInteger等类型),你不能使用直观的数学操作符(+,-,etc.)来操作它们。

  在Java.next中,一切皆是对象。你可以在所有的类型上使用相同的语法调用方法。
; clojure
(. 1 floatValue)
1.0

// groovy
1.floatValue()
===> 1.0

# ruby
1.to_f
=> 1.0

// scala
1.floatValue
res1: Float = 1.0


简洁的属性定义方式
  在Java中建立一个属性,你必须定义一个域,一个Getter,一个Setter,以及(通常)一个相应的构造函数,每一个定义都需要适当的访问修饰词。在Java.next中,你可以毕其功于一役。
; clojure
(defstruct person :first-name :last-name)

// groovy
class Person {
    def firstName
    def lastName
}

# ruby
Person = Struct.new(:first_name, :last_name)

// scala
case class Person(firstName: String, lastName: String) 

  如果你需要复写(或删除)一个Getter,Setter或是构造函数,你也可以做到,而无需重写其它部分。
  这还不是全部。所有这些语言信奉TMTOWTDI (There's More Than One Way To Do It),因此这儿不止一种方式可以实现上面同样的要求。


易用的集合类
  Java.next针对大部分重要的集合类提供了便利的语法:array与map。此外,你可以通把将函数作为参数将一系列操作连贯起来,而避免使用Java中那种显式的迭代或循环方式。譬如:找出100以内的奇完全平方数:
; clojure
(filter (fn [x] (= 1 (rem x 2))) (map (fn [x] (* x x)) (range 10)))
(1 9 25 49 81)

// groovy
(1..10).collect{ it*it }.findAll { it%2 == 1}
===> [1, 9, 25, 49, 81]

# ruby
(1..10).collect{ |x| x*x }.select{ |x| x%2 == 1}
=> [1, 9, 25, 49, 81]

// scala
(1 to 10).map(x => x*x).filter(x => x%2 == 1)
res20: Seq.Projection[Int] = RangeMF(1, 9, 25, 49, 81)

对哈希表(字典)有着同样便利的操作。

函数式编程
  上面集合类的便利使用只是函数式编程的一个特殊情形。Java.next中函数作为一等公民,支持将函数作为参数,将函数作为返回值,以及支持闭包。举一个简单的例子:创建一个函数adder,使得能计算与一个运行时指定的值之和:
; clojure
(defn adder [x] (fn [y] (+ x y)))

// groovy
adder = { add -> { val -> val + add } } 

# ruby
def adder(add)
  lambda { |x| x + add }
end

// scala
def sum(a: Int)(b: Int) = a + b


运算符重载
  在Java中,你不能重载运算符。因此你只能像这样操作BigDecimal:
// Java math
balance.add(balance.multiply(interest));

  Java.next允许你重载运算符。这样你能够创建新的类型并使得它像内建类型一样工作。譬如你能够新建一个ComplexNumber或RationalNumber,使其支持+,-,*,/运算符:
; Clojure
(+ balance (* balance interest))

// Groovy
balance + (balance * interest)

# JRuby
balance + (balance * interest)

// Scala 
balance + (balance * interest)


可维护的异常处理
  检查型异常(Checked Exception)是一个失败的试验。检查型异常的处理代码使得Java代码变得臃肿并掩盖了问题的关键。更糟糕的是,检查型异常使得代码的维护变得困难。
  Java.next不要求你声明检查型异常,也不要求你显式的处理检查型异常。这表明Java平台的其他语言完全可以避免Java语言中丑陋的检查型异常。

给已有类增加新方法
  在Java中,你不能给已有类添加方法。这使得面向对象模型变得很荒谬,开发者需要创建一些工具类,而这是与OO相违背的。
// Java (from the Jakarta Commons)
public class StringUtils { 
  public static boolean isBlank(String str) { 
    int strLen; 
    if (str == null || (strLen = str.length()) == 0) { 
      return true; 
    }  
    for (int i = 0; i < strLen; i++) { 
    if ((Character.isWhitespace(str.charAt(i)) == false)) { 
      return false; 
    } 
  }
}

  在Java.next中,你能够给已有类增加方法:
; Clojure
(defmulti blank? class)
(defmethod blank? String [s] (every? #{\space} s))
(defmethod blank? nil [_] true)

// Groovy
String.metaClass.isBlank = {
  length() == 0 || every { Character.isWhitespace(it.charAt(0)) }
}

# Ruby (from Rails)
class String 
  def blank? 
    empty? || strip.empty? 
  end 
end 

// Scala
implicit def strWrapper(s :String) = new {
    def isBlank = s.forall{ _.isWhitespace }
}


创建新的语言结构
  Java包括Java语言以及API库,这两部分是截然不同的:你能够创建新的API库,但你不能够添加新的语言特性。
  而在Java.next中,API库与语言特性没有明显的界线。你能够创建新的语言结构使得它像核心语言特性一样工作。例如,Clojure提供了一个and函数:
; clojure
(and 1 2) => 2

  你需要解决的不一定都是这样二元化的问题。你可能需要一个most函数,当它参数中大部分真时返回true。Clojure中没有这个,但你可以自己动手写一个:
; clojure
(most 1 2) => true
(most 1 2 nil) => true
(most 1 nil nil) => false

  这里的关键之处不是“我的语言是否需要一个most条件?”,而是不同的领域有不同的需求。在Java.next中,语言与库的界限被最小化,你可以添加适当的语言特性以适应你的领域需求,而不是相反。
  再举一个例子,考虑Ruby的attribute语法:
# Ruby
class Account
  attr_accessor :name
  dsl_attribute :type
end

  attr_accessor是Ruby固有的语法. dsl_attribute是我写的一个库方法,它允许你在做赋值操作的时候省略"=",像下面这样:
# normal attributes
account.name = "foo"

# equals-free attributes
account.type checking


结论
  这些Java.next语言有着相当多的共同点。尽管我使用一些孤立的例子来说明这些特点,但只有将它们一起使用时才能体现这些语言的真正威力。综合Java.next的所有特征,会导致一个完全不同的编码方式:

  ★ 在编码时你不再需要为了代码的可测试与适应性而采取保守方式:使用类工厂,设计模式以及依赖注入。作为代替,你可以构建一个最小解决方案,并随时改进它。
  ★ 在Java.next中,你可以开发更适合你问题的内部领域特定语言(DSLs)。


  以我的经验,这种编码方式能将代码量减少一个数量级,同时提高代码的可读性。
  很多人在寻找“next big language”。下一个“big language”已经在这里,但它不是一个单独的语言,而是一组概念的综合体,就如Java.next中表现出来的那样。
  过渡到Java.next配的上"big"这个称号吗?绝对可以。根据我的经验,一旦你作出转变,每一步都有着巨大的进步,包括学习曲线以及生产力。
  在这个系列的后续部分,我将讨论这些语言的不同之处。
分享到:
评论

相关推荐

    Android代码-Android-Next

    这个库是我在日常开发过程中积累下来的一些可复用组件,大部分都在我的工作项目和个人项目中有使用。 最新版本: Gradle集成 // core 核心库, 格式:jar和aar compile 'com.mcxiaoke.next:core:1.5.0' // task ...

    JMeterWebSocketSampler-1.0.2-SNAPSHOT.jar

    java.util.LinkedList$ListItr.next(LinkedList.java:886) JMeter.plugins.functional.samplers.websocket.ServiceSocket.getResponseMessage(ServiceSocket.java:125) JMeter.plugins.functional.samplers....

    java.util.ConcurrentModificationException 解决方法

    java.util.ConcurrentModificationException 解决方法 ... at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793) at java.util.HashMap$KeyIterator.next(HashMap.java:828) 例如以下程序(转

    vue.draggable.next:基于Sortable.js的Vue 3兼容拖放组件

    vue.draggable.next Vue组件(Vue.js 3.0)允许拖放并与视图模型数组同步。 对于Vue 2和Vue 1版本,请检查: : 基于并提供所有功能 演示版 现场演示 特征 全面支持功能: 支持触摸设备 支持拖动手柄和可选文本 ...

    JAVA数据结构——单链表的操作.docx

    } } (2)建立链表及操作LinkList.java JAVA数据结构——单链表的操作全文共11页,当前为第1页。package ch02; JAVA数据结构——单链表的操作全文共11页,当前为第1页。 import java.util.Scanner; public class ...

    单向循环链表python

    单向循环链表(Singly Circular Linked List)是一种特殊的链表,它与普通的单向链表非常相似,唯一的区别在于尾节点的next指针指向头节点而不是空。这样就形成了一个循环,使得链表中的节点可以通过循环遍历而不会...

    nextcloud.com::globe_showing_Asia-Australia:我们的网站

    贡献给nextcloud.com网站 请花一点时间阅读本文档...将存储git clone git@github.com:nextcloud/nextcloud.com next到您选择的文件夹中* git clone git@github.com:nextcloud/nextcloud.com next 在wp-content/themes

    java实验报告:实验六.doc

    输入参数(IN):Java.sql.PrepareStatement接口提供了一系列setXXX方法向SQL语句 传递输入参数,实现动态的SQL语句。在传递参数时,必须满足数据类型一致的要求. 6.输出参数(OUT):在调用一个存储过程时,可用setXXX...

    Moodle: 如何修改moodle——theme主题皮肤

    NULL 博文链接:https://justcoding.iteye.com/blog/2004089

    es.next.syntax.vim:ES.Vim的下一个语法

    es.next.syntax.vim:ES.Vim的下一个语法

    wangjiezhe.github.io:我的博客基于Hexo.NexT

    wangjiezhe.github.io:我的博客基于Hexo.NexT

    deerlost.github.io:对于创建博客的第三次尝试--Hexo.Next

    deerlost.github.io:对于创建博客的第三次尝试--Hexo.Next

    Berg Soft Next Suite 5 1.2013Delphi 7 - XE3

    Next Common -- fixed: Bug fixes and internal tweaks. NextGrid v5.8 -- added: Count property to InsertRow method. fixed: Bug fixes and internal tweaks. NextDBGrid v5.8 -- fixed: Bug fixes and ...

    lively.next:这是lively.next项目(https

    下一个这是的存储库。要求请注意,当前Lively服务器在MacOS,Linux或Windows Linux子系统上运行最佳。 可以在纯Windows上运行它,但需要进行其他调整。 确保已安装以下软件。 node.js版本8或更高版本。 吉特安装与...

    Android.App.Development.in.Android.Studio.Java.Android.Edition.For.Beginners.pdf

    In the next chapter, basics of the Java programming language are given with practical examples. Screenshots and code snippets are clearly given in the book to guide the reader. After the Java lecture...

    greenplum.jar 官方驱动 JDBC

    import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class Greenplum { public static void main(String args[]) throws Exception{ ...

    银河麒麟V10系统+飞腾CPU交叉编译OpenCV

    在/usr/local/下新建一个ffmpeg文件夹 mkdir /usr/local/ffmpeg 2、安装nasm nasm下载链接如下: https://www.linuxfromscratch.org/blfs/view/8.2/general/mercurial.html 进入网址后,界面如下 先点击右上角Next,...

    Java验证码Cage.zip

    Cage 是一个 Java 实现的验证码图片生成库,快速、小型和简单。 示例代码: public class QuickStart {  public static void main(String[] args) throws IOException {  Cage cage = new GCage()...

    java-实验报告.doc

    实验1 分析成绩单 1. 实验目的:掌握字符输入、输出流用法。 2. 实验代码: Fenxi: import java.util.*; public class Fenxi{ public static double getTotalScore(String s){ Scanner scanner=new Scanner(s); ...

Global site tag (gtag.js) - Google Analytics