Introduction




  A language made for Java developers.


                         @quicy
Xtendとは

● Eclipseからリリースされている
● 新しいJVM言語
● 少ない学習コストで
● 静的型で安全に
● Javaをより簡潔に
● Javaをより強力に
Xtendとは

● Javaプロジェクトで一緒に使う
● Xtendクラス → Javaクラスに変換
● interface, enum, annotationなどは
 全部Javaのまま
Xtendとは



Xtend == Java + α != 新言語


   Javaのエクステンション
Hello Xtend

class HelloXtend {
   def static void main(String[] args) {
      println('Hello Xtend')
   }
}
Hello Closure
import java.util.List
import static extension java.util.Collections.*
class HelloClosure {
   def static void main(String[] _) {
       println(positiveOnly(newArrayList(1, 5, 2, -10, 4)))
   }
   def static positiveOnly(List<Integer> values) {
       values.filter [it > 0]
   }
}
リアルタイムなJavaソース生成
Xtendのメリット

● 静的型
● 高い表現力
● Javaの型システムをそのまま使える
● IDEによる賢い補完
Javaをより簡潔に

● 型推論
● プロパティアクセス
● 演算子オーバロード
● 全てが「式」
Javaをより強力に

● クロージャ
● 拡張メソッド
● 強力なswitch式
● マルチプル・ディスパッチ
● テンプレート式


● Xtend全体がJavaのシュガー
Scalaでいいんじゃん?

● Scala使える状況ならScala使おう!
Xtend/いつ/なぜ?

● Javaソースが必要なとき
 (契約、GWT、etc...)

● Javaプログラマが
 少ない学習コストで
 今日からすぐに
 開発/保守を効率化するとき
Xtendの開発環境

● Eclipse + Xtend (☆Marketplace)
● 1. Javaプロジェクトを普通に作成
● 2. Xtend Classを作る
● 3. Quick Fixでライブラリを導入
● 4. あとはXtendクラスを書くだけ
● 5. 自動的にJavaソースに変換される
※ Mavenでもビルドできます
型推論~変数
val List<String> names = getTheListOfNames()

val names = getTheListOfNames()


※ 変数の型は省略できる
型推論~forループ
for (String name : getTheListOfNames())

for (name : getTheListOfNames())


※ 変数の型は省略できる
型推論~リターン型
def List<String> getTheListOfNames() {
  newArrayList("Tomte","Pippi","Carlson")
}

def getTheListOfNames() {
  newArrayList("Tomte","Pippi","Carlson")
}


※ リターン型は省略できる
型推論~クロージャ・パラメータ
getTheListOfNames().map(String name | "Mr. "+name)

getTheListOfNames().map(name | "Mr. "+name)


※ パラメータ型は省略できる
プロパティ・アクセス
person.getName()
person.name

person.setName("Foo")
person.name = "Foo"

obj.compute()
obj.compute


※ プロパティをより自然に扱える
演算子オーバロード
val apples = newArrayList(new Apple())
val oranges = newArrayList(new Orange())
val fruits = apples + oranges


※ 演算子の意味を多重定義できる
演算子の種類(1)
e1 += e2   e1.operator_add(e2)
e1 || e2   e1.operator_or(e2)
e1 && e2   e1.operator_and(e2)
e1 == e2   e1.operator_equals(e2)
e1 != e2   e1.operator_notEquals(e2)
e1 < e2    e1.operator_lessThan(e2)
e1 > e2    e1.operator_greaterThan(e2)
e1 <= e2   e1.operator_lessEqualsThan(e2)
e1 >= e2   e1.operator_greaterEqualsThan(e2)
e1 -> e2   e1.operator_mappedTo(e2)
演算子の種類(2)
e1 .. e2   e1.operator_upTo(e2)
e1 + e2    e1.operator_plus(e2)
e1 - e2    e1.operator_minus(e2)
e1 * e2    e1.operator_multiply(e2)
e1 / e2    e1.operator_divide(e2)
e1 % e2    e1.operator_modulo(e2)
e1 ** e2   e1.operator_power(e2)
! e1       e1.operator_not()
- e1       e1.operator_minus()
すべてが「式」
val data = if (file.exists) {
   fileContentsToString(file)
 } else {
   'has no data'
 }


※ 文じゃないから評価結果が値になる
※ caseやtry~catchも式です
拡張メソッド~ローカル拡張
class Printer {
  def void print(Person person) {
    println(person.fullName)
  }
  def getFullName(Person p) {
    p.firstName + " " + p.lastName
  }
}

クラスにメソッドを外部から追加する
イメージで呼び出せるようになる
拡張メソッド~Inject
class Printer {
 @Inject extension PersonExtension

    def print(Person person) {
      println( person.fullName )
    }
}


※ 外部定義された拡張をDIで適用する
拡張メソッド~static import
import static extension java.util.Collections.*


静的拡張ライブラリを使える。
コレクションや文字列の拡張が便利。
高階関数+クロージャが超強力!
クロージャ(1)~ブロック
val names = people.map [ p | p.name ]


※ コレクション処理がとても簡単に
クロージャ(2)~ラムダ式
val predicate =
   [Person person | "Hans" == person.name]

people.filter(predicate)



※ ラムダ式で生成した関数を
 高階関数に渡せる
クロージャ(3)~簡略化
people.filter[ Person p | "Hans" == p.name ]
people.filter[ p | "Hans" == p.name ]
people.filter[ "Hans" == it.name ]
people.filter[ "Hans" == name ]



※ 型推論や暗黙itパラメータで簡略化
クロージャ(4)~Builder DSL
html [
 head [
   title [$("XML encoding with Xtend")]
 ]
 body [
   h1 [$("XML encoding with Xtend")]
   p [$("this dsl can be used as alternative to XML")]



※ BuilderなどのDSLとしても有効
テンプレート式
val fullName = '''Name: «p.firstName» «p.lastName»'''

def getFullName(Person p) '''
    Fist name: «p.firstName»
    Last name: «p.lastName»
'''


※ テンプレート文字列を簡単に作れる
※ IF/FORなどの制御構造も埋め込める
Switch式
val Shape shape = ...
val desc = switch (shape) {
  Rectangle case shape.width == shape.height :
   "Square ("+shape.width+")"
  Rectangle :
   "Rectangle ("+shape.width+" x "+shape.height+")"
  Circle :
   "Circle ("+shape.diameter+")"
  default :
   "Don't know"
}

※ 型ガードと条件検査を同時にできる
マルチプル・ディスパッチ
def example() {
  val Shape s = new Rectangle()
  println(s.label)
}
def dispatch label(Shape s) {
   "some shape"
}
def dispatch label(Rectangle r) { ←
   "a rectangle"
}

※ 実行時の型でメソッドが選択される
どんどん進化中!

● 言語機能もIDEも、まだ少し力不足
● 開発が活発です
● ちょっと足りないなと思うものも、
 次々に実装されていきます
+1

● 開発者がイケメン
● Sven Efftingeさん素敵です
Xtendのまとめ

● 少ない学習コストで
● 静的型で安全に
● Javaをより簡潔に
● Javaをより強力に

Introduction Xtend