学学手册mobile.365-838.com

mobile.365-838.com 1

6. 世界特定语言

Groovy 有大多性格,使它万分适合写DSL(领域特定语言)。这么些特征包活:

  • 抱有委托机制的闭包;
  • 点号(.)和讲话末尾的分店(;)是可选的;
  • mobile.365-838.com,运算符的重载(例如,加号,减号等);
  • methodMissingpropertyMissing 方法

Tip
至于 DSLs (Domain Specific Languages ),可以参见此书《DSLs In
Action》。

特定领域语言能够用来多数目标,如允许领域专家阅读和编排代码,或澄清事情逻辑的意义。它们允许购买发售专家阅读或编辑代码而不要是一名编制程序专家。

1. 委托

在 Groovy
中,可以将二个代码块(或闭包)作为参数,然后使用二个局地变量作为委托调用它。例如,下边包车型大巴代码用来发送短信:

class SMS {
      def from(String fromNumber) {
            // set the from
      }
      def to(String toNumber) {
            // set the to
       }
      def body(String body) {
            // set the body of text
     }
     def send() {
           // send the text.
     }
}

然则,在 Java 中你必要接纳如下的秘诀:

SMS m = new  SMS();
m.from("555-432-1234");
m.to("555-678-4321");
m.body("Hey there!");
m.send();

在 Groovy 中得以定义用来发送短信的静态方法,依照 DSL
风格的利用方法,代码块壹般作为三个闭包)。

def static send(block) {
    SMS m = new SMS()
    block.delegate = m
    block()
    m.send()
}

这将 SMS 对象设置为代码块的寄托,以便将艺术转载给它。
有了那几个,你未来可以实行以下操作:

SMS.send {
    from '555-432-1234'
    to '555-678-4321'
    body 'Hey there!'
}

关于 delegate, 个人明白,闭包中的 delegate 类似于类中的 this.

2. 重载运算符

在 Groovy 中,你能够应用运算符的英文单词来重载对应的运算符,例如,plus
指的是“+”运算符,minus 指的是“-”运算符。

mobile.365-838.com 2

除了nextprevious
运算符未有参数外,其余的运算符都有二个参数。上边包车型大巴事例大家来创建Logic类富含
3个boolean 类型的变量,来定义andor 方法。

class  Logic  {
    boolean value

    Logic(v) {this.value = v}

    def and(Logic other) {
        this.value && other.value
    }
    def or(Logic other) {
        this.value || other.value
    }
}

大家能够运用那个办法,看是还是不是和我们预料的1模同样。

def  pale = new Logic(true)
def old = new Logic(false)

// Notice that using the built-in && operator 
// uses “Groovy truth” and returns true 
// because both variables are non-null .
println "groovy truth: ${pale && old}" // true

println "using and: ${pale & old}"  // false 
println "using or: ${pale | old}"  // true

上边包车型大巴例证定义个重载<<- 的类。

class Wizards {
    def list = []
    def leftShift(person) { list.add person }
    def  minus(person) { list.remove person }
    String toString() { "Wizards: $list" }
}

def  wiz = new  Wizards()

wiz << 'Gandolf'
println wiz
wiz << 'Harry'
println wiz
wiz - 'Harry'
println wiz

出口结果为:

Wizards: [Gandolf]
Wizards: [Gandolf, Harry]
Wizards: [Gandolf]

您也能够兑现 Map
风格的getAtputAt方法的重载,那允许你利用括号的语法格局,如下:

def value = object[parameter] // uses getAt
object[parameter] = value // uses putAt

叁. 缺点和失误的秘诀和属性

在此以前介绍过,Groovy在运行时提供methodMissing主意了来贯彻的机能的方式。
def methodMissing(String name, args)
只是,Groovy还提供了一种格局来阻止使用Groovy的属性语法访问缺点和失误的习性。使用
propertyMissing(String name)来促成属性的走访,通过propertyMissing(String name, Object value)来修改属性。
看上边包车型大巴例证,那里有1个化合物类的DSL片段描述:

class  Chemistry  {
    public static void exec(Closure block) {
        block.delegate = new  Chemistry()
        block()
    }

    def propertyMissing(String name) {
        def  comp = new  Compound(name)
        (comp.elements.size() == 1 && comp.elements.values()[0]==1) ?
            comp.elements.keySet()[0] : comp
    }
}

在那个例子中,propertyMissing
创设三个新的Compound对象并回到,尽管Compound目的惟有多少个成分的话,则赶回这些因素对象。那能够用来成立一个基于缺点和失误属性的名字的Compound对象。看例子:

def  c = new  Chemistry()
def water = c.H2O
println water
println water.weight

那是总结访问二个性质为H二O,会触发 propertyMissing 方法调用。
因而接纳静态 exec
方法,该DSL通过将化学实例作为闭包的寄托来促成其全方位潜力,那允许以下示例:

Chemistry.exec {
        def water = H2O
        println water
        println water.weight
}

那是透过调用ChemistrypropertyMissing 方法一样的职能来创设 H二O
组件。

Tip
Chemisty
的完好代码,请访问Chemisty;

7. trait 语法

trail 就像是全体暗许方法和总体性的接口,Groovy中的trait
是碰着Scale语言里的trait的开导。
在Java第88中学大家领略在接口里面能够有暗中认可方法,trail跟Java第88中学的接口很像,可是全数修改情况(属性)的力量。那样会愈发灵敏,不过也要相当的小心。

1. 定义trait

大家来定义四个trait:

trait Animal {
    int hunger = 100
    def  eat() { println "eating"; hunger -= 1 }
    abstract int getNumberOfLegs()
}

本条概念的trait具备艺术,属性和架空方法。假如1个类要完毕他,必须兑现对应的空洞方法。

2. 使用trait

要想完毕trait,跟Java中的类完毕接口同样,使用implements 关键字。

class Rocket  {
    String name
    def  launch() { println(name + " Take off!") }
}
trait MoonLander {
    def land() { println("${getName()} Landing!") }
    abstract String getName()
}
class  Apollo  extends  Rocket implements  MoonLander {
}

您能够如下代码来使用它:

def  apollo = new  Apollo(name: "Apollo 12")
apollo.launch()
apollo.land()

出口结果为:

Apollo 12 Take off!
Apollo 12 Landing!

您能够在1个类上完成多少个trait,例如:

trait Shuttle {
    boolean canFly() { true }
    abstract int getCargoBaySize()  
}
class MoonShuttle  extends  Rocket
    implements  MoonLander, Shuttle {
    int getCargoBaySize() { 100 }
}

然后可以如下使用:

MoonShuttle m = new  MoonShuttle(name: 'Taxi')
println "${m.name} can fly? ${m.canFly()}"
println "cargo bay: ${m.getCargoBaySize()}"
m.launch()
m.land()

输出结果为:

Taxi can fly? true
cargo bay: 100
Taxi Take off!
Taxi Landing!
admin

网站地图xml地图