Edited at

RubyistがGroovyを始めてみた

More than 5 years have passed since last update.


RubyistがGroovyを始めてみた

これは G*(Groovy, Grails ..) Advent Calendar 2013 の18日目になります。

皆さんためになる記事を書かれている中、一人レベルが低くて申し訳ないのですが、カレンダーが空いていたので自分がGroovyをRubyと比較しながら勉強したまとめを書いてみます。

既に語り尽くされた内容のような気もしますがご容赦頂ければと思います。


Contents


  • 基本的なところ

とりあえずHello World / メソッドの定義 / classの定義 / 変数の定義 / メソッドのカッコを省略する


  • RubyのあれはGroovyだとなんなの

times / each / map / flat_map / reduce / ||= / try / ArrayとHash / getter・setter / [ ]メソッド


  • 外部ライブラリを使いたい


基本的なところ

では基本的なところから。


■とりあえずHello World

Hello World、基本ですよね。Groovyはスクリプトとしても動くので、printlnを書き下せばできます。


Ruby

puts "Hello World"



Groovy

println "Hello World"



■メソッドの定義

メソッドを定義するには、どちらも def を使います。


Ruby

def func1(arg)

puts arg
end


Groovy

def func1(arg) {

println arg
}


■classの定義

Groovyの場合、このあたりはJava準拠です。


Ruby

class Foo

def greeting
puts "Hello, I am Foo"
end
end

class Bar < Foo
def greeting
puts "Hello, I am Bar"
end
end

Bar.new.greeting



Groovy

class Foo {

def greeting() {
println "Hello, I am Foo"
}
}

class Bar extends Foo {
def greeting() {
println "Hello, I am Bar"
}
}

new Bar().greeting()



■変数の定義

Rubyだと何も宣言せずいきなり書けますが、Groovyだとdefを使って宣言しておく必要があるみたいです。(追記、スクリプトだと要らないかも?)

def ってメソッド定義にも使うのに、ちょっと気持ち悪いです。


Ruby

value = 10



Groovy

def value = 10



■メソッドのカッコを省略する

Hello Worldで分かるように、メソッドのカッコを省略できます。でも引数がないときはカッコをつけないといけないみたいです。


Ruby

def func1(arg)

puts arg
end

def func2
func1 "Hello"
end

func1 "Good morning"
func2



Groovy

def func1(arg) {

println arg
}

def func2() {
func1 "Hello"
}

func1 "Good morning"
func2()



RubyのあれはGroovyだとなんなの

普段使うRubyのあれはGroovyだとどんな風になっているのかまとめてみました。


■ArrayとHash

Groovyのハッシュリテラルは [] を使います。


Ruby

[1,2,3,4]

{ "a" => 1, "b" => 2, "c" => 3 }
[] # 空配列
{} # 空ハッシュ


Groovy

[1,2,3,4]

[a:1, b:2, c:3]
[] //空配列
[:] //空ハッシュ


■times

みんな大好き times メソッド


Ruby

10.times { |n| puts n }



Groovy

10.times { n -> println(n) }



■each

みんな大好き each メソッド


Ruby

["a", "b", "c"].each { |arg| puts arg }



Groovy

["a", "b", "c"].each {  arg -> println arg }



■map

Groovyはcollect派なのですね。また、コレクション*.メソッド という書き方で、コレクション全体にメソッドを適用する書き方ができるみたいです。


Ruby

[1,2,3].map { |n| n + 1 }

["1", "2", "3"].map(&:to_i)


Groovy

[1,2,3].collect { n -> n + 1 }

["1", "2", "3"]*.toInteger()


■flat_map

collectManyってあまり見かけない言い回しな気がします。


Ruby

[ [1,2,3], [4,5,6], [7,8]].flat_map { |arg| arg.take(2) }



Groovy

[ [1,2,3], [4,5,6], [7,8]].collectMany { arg -> arg.take(2) }



■reduce

reduceじゃなくてinject派でした。


Ruby

[1,2,3,4,5].reduce { |accum,elem| accum + elem }



Groovy

[1,2,3,4,5].inject { accum, elem -> accum + elem }



■||=

Rubyでわりと便利に使える ||=。 Groovyだと ?: とか(まだよくわかってない)?

三項演算子の 2項目を省略できる感じでしょうか。


Ruby

value ||= 10



Groovy

value = value ?: 10



■try (ActiveSupport)

モナディックな感じで処理を書くのに便利なObject#try。

Groovy だと オブジェクト?.メソッドと書けるみたいです。ちょっと気持ち悪い。


Ruby

foo.try(:some_method)



Groovy

foo?.some_method()



■getter・setter

Rubyでインスタンス変数に外部からアクセスするときには必ずgetter・setterを経由しました。

Groovyでは普通にプロパティとしてアクセスできますが、getter・setterを定義することもできるみたいです。

あと、関係ないですけれども、Groovyってprivateでも外からアクセスできちゃったりしますか?


Ruby

class Foo

attr_reader :name

def initialize
@name = "John Doe"
end

def name=(name)
@name = name if name.length > 0
end
end

foo = Foo.new
puts foo.name
foo.name = "Adam Adams"
puts foo.name



Groovy

class Foo {

private def name = "John Doe"

def getName() {
name
}

def setName(name) {
if(name.length() > 0) {
this.name = name
}
}
}

foo = new Foo()
println foo.name
foo.name = "Adam Adams"
println foo.name



■[ ] メソッド

Rubyではクラスに[ ] メソッドを定義すると、配列のようにアクセスすることができます。

Groovyでは getAtとputAtメソッドを定義すると同様の事ができました。


Ruby

class FooContainer

def initialize
@data = []
end

def [](index)
@data[index]
end

def []=(index, value)
@data[index] = value
end
end

container = FooContainer.new
container[0] = "Hello"
container[1] = container[0]
puts container[1]



Groovy

class FooContainer {

private def data = []

def getAt(index) {
data[index]
}

def putAt(index, value) {
data[index] = value
}
}

container = new FooContainer()
container[0] = "a"
container[1] = container[0]
println container[1]



外部ライブラリを使いたい

標準以外のライブラリを使いたいとき、Rubyではgem でインストールして、スクリプト中でrequire すればいいので超簡単。Java系の言語はclass pathがどうとか、面倒くさいしよくわからないので、どうしましょう。


■Gradleを使うみたい

gradleはRubyのrake みたいなもので、ビルドしたり依存関係を管理したりしてくれます。

プラグインがとても便利で、Java系言語の面倒くさいところをだいぶ面倒みてくれます。


インストール

まずどうにかしてGradleをインストールします。Homebrewだったら以下のようにします。

brew install gradle


この際プロジェクトを作る

プロジェクト用のディレクトリを作ってその直下で下記のようにコマンドを入力します。

gradle init


build.gradleを編集する

プロジェクト用のファイルができるので build.gradle を編集して、使いたいライブラリを記述しておきます。

例えば、下のは RxJavaを使いたい場合です。

ソースコードは src/main/groovy以下に配置するようにしておきます。


build.gradle

apply plugin: 'groovy'

apply plugin: 'application'

repositories {
mavenCentral()
}

dependencies {
compile group:'com.netflix.rxjava', name:'rxjava-groovy', version:'0.15.0'
}

mainClassName = 'test.Main'



実行する

あとはgradle経由で実行するだけです。いいようにライブラリをダウンロードしてclass pathも設定してくれます。

gradle run


Disclaimer

ちゃんとしたGroovy使いの方からみて、「それは違うよ!」とか「こっちのほうがいいよ!」という部分があるかもしれません。もしそういう部分がありましたら、指摘して頂けるとありがたいです!