Xtend官方文档-第一部分
第一章 入门
第一节 简介
Xtend是一种静态类型的编程语言,可以转化为可理解的Java源代码。其语法和语义构成基于Java编程语言,但在许多方面得到改进:
u 扩展方法 - 增强封闭类型新功能
u Lambda表达式 - 简洁的匿名函数常量语法
u ActiveAnnotations (积极的注解)- 注解处理的增强因子
u 运算符重载 - 使您的库更具表现力
u 强大的开关表达式 - 隐式的类型转换
u 多重调度 - 又名:多态方法调用
u 模板表达式 - 具有智能空白处理
u 没有语句 - 一切都是表达
u 属性 - 简化了getter和setter的访问
u 类型推断 - 可以少写类型签名
u 完全支持Java泛型 - 包括所有一致性和转换规则
u 翻译为Java而不是字节码 - 了解发生了什么,并可将代码用于Android或GWT等平台
与其他JVM语言不同,Xtend 与Java 具有零互操作性问题:您编写的所有内容都与预期的Java代码完全一致。与此同时,Xtend更加简洁、可读和表现力。Xtend的小型库只是一个薄层,提供有用的实用工具和在顶层提供Java开发工具包(JDK)的扩展。
当然,也可以通过Java来完全透明地调用Xtend方法。此外,Xtend还提供现代风格的、基于Eclipse的IDE,并与Eclipse Java开发工具(JDT)紧密集成,包括调用层次结构、重命名重构、调试等功能。
第二节 Hello,World
就像你看到看到其他任何语言一样,第一件事是Hello World的例子。在Xtend中,它代码为:
class HelloWorld {
def static void main(String[] args) {
println("Hello World")
}
}
Xtend看起来和Java非常相似。乍一看,主要区别似乎是def关键字来声明一个方法。同样在Java中,必须将类和main方法定义为应用程序的入口点。诚然,Hello World程序没有体现出Xtend的优势。可当你让程序真正的做一些事情时,真正的表现力将会释放出来,这将会在下一秒学到。
Xtend类驻留在普通的Eclipse Java项目中。一旦安装了SDK,Eclipse将自动将所有类转换为Java源代码。默认情况下,您将在源代码文件夹xtend-gen中找到它。hello world示例被转换为以下Java代码:
// Generated Java Source Code
import org.eclipse.xtext.xbase.lib.InputOutput;
public class HelloWorld {
public static void main(final String[] args) {
InputOutput.<String>println("Hello World");
}
}
生成的Java代码中唯一令人惊讶的可能是引用库的InputOutput类。它是运行时库(runtime library )的一部分,一个很好的工具,可以非常方便地在表达式中使用。
您可以将Xtend类放入任何Eclipse或Maven的Java项目源文件夹中。如果项目尚未正确配置,Eclipse会告诉你丢失的库。xtend.lib必须在类的路径上。IDE将提供一个快速修复来添加它。
下一件事是,在工作区(workSpace)中,实现一个示例项目。在在Eclipse导航(Navigator)视图任意位置单击鼠标右键,并选择New(新建)→Example(示例)...。
在出现的对话框中,您将找到Xtend的两个示例:
l Xtend介绍示例(Xtend Introductory Examples),包含几个示例代码片段,说明Xtend的某些方面优势。例如,它显示了如何允许编写如下代码构建API:
assertEquals(42.km/h, (40_000.m + 2.km) / 60.min)
下一节中详细介绍的电影示例也包括在那里。
l Xtend的Euler解决方案(Xtend Solutions For Euler),您可以在Project Euler中找到一些问题的解决方案。这些例子利用了Xtend的整体表现力。例如Euler问题1可以用这个表达式来解决:
(1..999).filter[ i | i % 3 == 0 || i % 5 == 0 ].reduce[ i1, i2 | i1 + i2 ]
第三节 电影示例
电影示例包含在示例项目Xtend Introductory Examples(src / examples6 / Movies.xtend)中,是读取关于电影的数据文件,并对其进行一些分析。
数据
电影数据库是纯文本文件(data.csv),具体描述电影的数据集。以下是一个示例数据集:
Naked Lunch 1991 6.9 16578 Biography Comedy Drama Fantasy
值由两个空格分隔。列是:
1.标题(title)
2.年份(year)
3.评级(rating)
4.票数(numberOfVotes)
5.类别(categories)
让我们定义一个表示数据集的数据类Movie:
@Data class Movie {
String title
int year
double rating
long numberOfVotes
Set<String> categories
}
电影类是POJO,数据集中的每列都有强类型字段。@Data注解将会把类变成一个不变值类,那么它会得到:
l 每个字段的getter方法,
l 一个hashCode()/ equals()实现,
l Object.toString()实现,
l 构造函数按所有字段的声明顺序接受值。
解析数据
现在让我们在同一个文件中添加另一个类,并一个名为movies的字段,初始化为列表。我们解析文本文件并将数据记录转换为Movie类:
import java.io.FileReader
import java.util.Set
import static extension com.google.common.io.CharStreams.*
class Movies {
val movies = new FileReader('data.csv').readLines.map [ line |
val segments = line.split(' ').iterator
return new Movie(
segments.next,
Integer.parseInt(segments.next),
Double.parseDouble(segments.next),
Long.parseLong(segments.next),
segments.toSet
)
]
}
字段的类型可以从右侧的表达式来推断。这被称为局部类型推断,在Xtend中随处可见。我们希望该字段是final,所以我们使用关键字val,将其声明为一个值变量(只读变量)。
右侧的初始化,首先创建一个新的FileReader。然后在该实例中调用方法readLines()。但是如果你看看FileReader,你不会找到这个方法。事实上,readLines()是来自Google Guava的CharStreams的静态方法,它被导入作为扩展( extension)。扩展允许我们使用这种可读的语法。
import static extension com.google.common.io.CharStreams.*
CharStreams.readLines(Reader)使用另一个扩展方法map返回List<String>类型,其在运行时库中定义的(ListExtensions.map(...)),并自动导入,因此可用于所有列表。该map扩展需要一个函数作为参数。它基本上为列表中的每个值调用该函数,并返回另一个包含函数调用结果的列表。实际上,这个映射是懒惰地执行的,如果你不访问列表的结果值,那么映射函数就永远不会被执行。
而函数对象是使用lambda表达式(方括号中的代码)创建的。在lambda中,我们处理文本文件中的一行,并通过使用两个空格字符作为分隔符作为分割符,将其转换为movie。对于拆分操作的结果,调用iterator()方法。您可能知道String.split(String)返回一个字符串数组(String[]),当我们调用Iterable.iterator()时,Xtend会自动转换为列表。
val segments = line.split(' ').iterator
现在我们使用迭代器,为每个产生的String 创建一个Movie实例。数据类型转换,通过从包装器类型调用静态方法来完成(例如String转为int)。Iterable的其余部分,变成一组类别(categories)。因此,迭代器调用扩展方法IteratorExtensions.toSet(Iterator<T>),以完成其余值的转换。
return new Movie (
segments.next,
Integer.parseInt(segments.next),
Double.parseDouble(segments.next),
Long.parseLong(segments.next),
segments.toSet
)
响应查询
现在我们已经将文本文件解析成了List<Movie>,我们已经准备好对它执行一些查询了。我们使用JUnit来使单个查询可执行并确认其结果。
查询1:动作片数量是多少?
@Test def numberOfActionMovies() {
assertEquals(828,
movies.filter[ categories.contains('Action') ].size)
}
首先,对movies过滤(filter)。lambda表达式检查当前影片的类别是否包含条目'Action'。请注意,不像我们用来将文件中的行转换成movies的lambda,这次我们没有声明一个参数名。所以上面表达式,我们可以这样写:
movies.filter[ movie | movie.categories.contains('Action') ].size
但是由于我们省略了参数名称和垂直条|,所以变量被自动命名it。it是一个隐式变量。它的用法类似于隐式变量this。所以也可以写成这样:
movies.filter[ it.categories.contains('Action') ].size
或甚至更紧凑地写成前面那样:
movies.filter[ categories.contains('Action') ].size
最后我们size也会调用生成的iterable,这也是一个扩展方法。它在实用程序类(utility class )IterableExtensions中定义。
查询2:80年代最好的电影是哪一年上演的?
@Test def void yearOfBestMovieFrom80s() {
assertEquals(1989,
movies.filter[ (1980..1989).contains(year) ].sortBy[ rating ].last.year)
}
在这里,我们过滤1980年至1989年(80年代)范围内的所有电影。操作符“..”又是一个在IntegerExtensions定义的扩展,并返回IntegerRange的实例。操作符重载在第二章中说明。
由此产生的迭代排序,则IterableExtensions.sortBy按movies的rating进行排序。由于它按升序排列,我们从列表中取出最后一个电影并返回其year。
我们也可以按降序排序,还可以列出列表的头:
movies.filter[ (1980..1989).contains(year) ].sortBy[ -rating ].head.year
另一个可能的解决方案是颠倒排序列表的顺序:
movies.filter[ (1980..1989).contains(year) ].sortBy[ rating ].reverseView.head.year
请注意,首先排序,然后取最后或第一个,代价稍大一点。我们可以使用方法reduce更有效地找到最好的电影。你可以自己尝试一下。
前面的例子调用movie.year以及movie.categories,实际上是访问相应的getter方法。
查询3:前两部电影的得票总数是多少?
@Test def void sumOfVotesOfTop2() {
val long sum = movies.sortBy[ -rating ].take(2).map[ numberOfVotes ].reduce[ a, b | a + b ]
assertEquals(47_229L, sum)
}
首先,电影按评级排序,然后我们取最好的两个。接下来,使用map函数将电影列表的numberOfVotes形成新的列表。现在我们有List<Long>,可以通过添加值将其缩小到一个Long。
你也可以用reduce代替map和reduce。你知道怎么做吗?
Xtend官方文档-第一部分相关推荐
- [译]1-Key-Value Coding Programming Guide 官方文档第一部分
Key-Value Coding Programming Guide 官方文档第一部分 2018.9.20 第一次修正 iOS-KVC官方文档第一部分 Key-Value Coding Program ...
- Xtend官方文档——第二部分(一)
第二章 语言文档参考(一) 第一节 Java互操作性 Xtend像Java一样,是一种静态类型的语言.实际上,它完全支持Java的类型系统,包括基本类型,如int或者boolean.数组以及类路径上 ...
- 对 Windows 官方文档的一点吐槽
对 Windows 官方文档的一点吐槽 正文 当你在百度搜 Windows 系统的一些问题,所见之处尽是<小编来教大家><第一步第二步第三步第四步第五步--><方法一方法 ...
- 006-基于hyperledger fabric1.4( 官方文档)编写第一个应用【外部nodejs调用】
一.概述 官方原文地址 Writing Your First Application 如果对fabric网络的基本运行机制不熟悉的话,请看这里. 注意:本教程是对fabric应用以及如何使用智能合约的 ...
- 跟着官方文档学DGL框架第一天——DGL概览
主要参考:https://docs.dgl.ai/tutorials/basics/1_first.html DGL是什么 DGL是一种用于简化图神经网络实现的包,感觉官方文档写得很亲民,打算好好拜读 ...
- 文件标识符必须为双精度类型的整数值标量_【翻译】VTK官方文档 - vtk文件格式
本文翻译自vtk官方文档:vtk_file_format 文末有链接 VTK提供了许多源对象和编写器对象,用于读取和写入流行的数据文件格式,此外,VTK也提供了自己的文件格式.创建一种数据文件格式的主 ...
- 深入理解Java 8 Lambda表达式(Oracle官方文档版)
Java 8 问世三年了,9马上也要问世了,所以,嗯,我要开始学8了-- 官方文档:http://docs.oracle.com/javase/tutorial/java/javaOO/lambdae ...
- 《Redis官方文档》用Redis构建分布式锁
<Redis官方文档>用Redis构建分布式锁 用Redis构建分布式锁 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现 ...
- Swift 4官方文档中文版 The Basic(上)
Swift学习交流群: 313838956 本群由Guards翻译组创建并维护, 志于给认真想学习Swift的同学打造一个良好的交流圈子. 该文章翻译自Apple官方文档: The Swift 4 P ...
最新文章
- c++ socket 结构体
- yolo 负样本_目标检测介绍之YOLO与SSD
- azkaban mysql参数_azkaban参数详解
- C++:值传递、指针传递、引用传递
- 老男孩的学生优秀博文及内部教学文章
- Python - SimpleHTTPServer and CGIHTTPServer
- 怎么用虚拟机搭建云服务器,利用虚拟机搭建云服务器
- 特征值、特征向量及相似矩阵
- [STM32学习笔记]野火MINI开发板ISP一键下载电路
- 基于wifi的物联网技术,主要有哪些优势?
- Java Mysql工具类封装
- 关于产品的一些思考——八千里科技之谁叫我起床
- 【论文阅读 | 冷冻电镜】RELION 4.0 中新的 subtomogram averaging 方法解读
- 10 06 01 繁杂
- python英文分词库_Python中文分词库jieba,pkusegwg性能准确度比较
- 从生活角度学习c++
- 5700: 还钱问题
- STM32H743使用PA0,PA1作为ADC输入的坑!!
- 室内定位系统算法--无线时钟同步的比较
- 小信号放大电路的频率特性
热门文章
- app通过电商变现方式探讨
- win7系统下阿里旺旺无法登陆怎么解决
- 红星美羚育儿经:宝宝上火,是奶粉的祸?
- 荒野行动8月1日服务器维护,荒野行动手游12月21日服务器维护到几点 12月21日具体开服时间公告...
- 视频监控安防平台-国标28181平台(支持国标28181转RTSP/RTMP/HLS/WEBRTC直播)
- Win10无法使用内置管理员账户打开应用解决办法
- 函数式程序设计为什么至关重要
- 金蝶OSF接口(s-HR系统)调用示例
- graphpad prism怎么添加图例_Graphpad Prism:如何制作柱状图
- hgroup元素与figcaption元素的结合使用