2013年2月9日土曜日

Groovyでメソッドの引数に型を指定する意味

強い動的型付け言語であるGroovy。
JVM上で動く言語でありながら、まるでPHPの様にサクサクコーディングが出来る素敵な言語です。
強い動的型付けである為、型の宣言をする必要が無く、ソースがスッキリします。
ただし、PHP等のスクリプト言語における動的型付けと少し異なるのが、
ただし型の宣言は省略出来るのであって、宣言出来ない訳ではありません。つまり、
「型の指定はしなくても良いけど、する事も出来る」
という訳です。
じゃあ型を指定する場合は一体何が嬉しいの?という点を今回纏めてみました。
以下早速サンプルソースです。動的型付け言語の特徴として、コンパイル時点ではなく、実行時点でなければエラーの検出が出来ないという特徴を活かして説明しています。
*2012/02/12 追記:PHPでは仮引数でクラスやインタフェースを指定する事が出来ます。

型を指定しない場合
def test(a){
println a;
a = a.toLong() //Stringが渡されるとこの時点で例外が発生
println a.getClass()
}

test(1)
test("a")

以下、コンパイルと実行
[koji:groovy]$ groovyc type_check.groovy
[koji:groovy]$ groovy type_check
1
class java.lang.Long
a
Caught: java.lang.NumberFormatException: For input string: "a"
java.lang.NumberFormatException: For input string: "a"
at type_check.test(type_check.groovy:4)
at type_check$test.callCurrent(Unknown Source)
at type_check.run(type_check.groovy:10)

test(1)は問題なく実行され、test("a")はメソッドの途中まで実行されて、toLong()を実行するタイミングで例外が発生しています。
コレはString型にはtoLong()メソッドが存在しない為です。


型を指定する場合
def test(Integer a){
        println a;
        a = a.toLong()
        println a.getClass()
}

test(1)
test("a") //そもそもStringをとるtestメソッドが存在しないのでこの時点で例外が発生

以下、コンパイルと実行
[koji:groovy]$ groovyc type_check.groovy
[koji:groovy]$ groovy type_check
1
class java.lang.Integer
Caught: groovy.lang.MissingMethodException: No signature of method: type_check.test() is applicable for argument types: (java.lang.String) values: [a]
Possible solutions: test(java.lang.Integer), getAt(java.lang.String), wait(), use([Ljava.lang.Object;), wait(long), is(java.lang.Object)
groovy.lang.MissingMethodException: No signature of method: type_check.test() is applicable for argument types: (java.lang.String) values: [a]
Possible solutions: test(java.lang.Integer), getAt(java.lang.String), wait(), use([Ljava.lang.Object;), wait(long), is(java.lang.Object)
at type_check.run(type_check.groovy:10)
[koji:groovy]$

test(1)は問題なく実行されていますが、こちらの場合はtest("a")を実行したタイミングで例外が発生しています。
コレはtest()というメソッド名でStringを受け取るメソッドが存在しないために発生しているエラーです。

ざっくりまとめると、
前者の場合:PHP等の動的型付けなスクリプト言語では一般的なパターン
後者の場合:Java等の静的型付けなお固い言語では一般的なパターン
となります。

ただし注意しなければ成らないのが、後者の場合でもGroovyのコンパイルでは型チェックが出来ないという事です。プログラムが実行され、該当箇所が実際に実行されるまでエラーになるかどうか分かりません。
コレはGroovyが動的型付け言語であるためです。(型チェックが出来ないのは前者も同様)
例えば、以下のように後者のパターンの実行方法を変えた場合にはエラーは発生しません。

test(1)
if( 0 ) {
        test("a")  //ここは実行されないからプログラム的にはエラー無し
}

じゃあ態々メソッドの引数に型の指定をしてもメリット無いじゃないかと思われるかもしれませんが、当然メリットもあります。

まず、型を指定しておくと実行時例外にはなるものの、メソッドの中身は実行されないため、渡された引数が本当に意図した型なのかという事をメソッドの中で一々チェックしなてくても良い点。

2点目が、Groovyで作成したライブラリなどをJavaで利用する時。Groovyのソース上で型を指定しておくとJava側で意図しない値(今回の例であればString)を渡すようなプログラムを書いた場合、Javaのコンパイル時点でその誤りを検出出来ます。

Groovyでメソッドの引数に型を指定しない場合の前者、型を指定した場合の後者のjavapは以下のようになります。(該当メソッド部分のみ抽出)

前者の場合
[koji:groovy]$ javap type_check | grep test
  public java.lang.Object test(java.lang.Object);

後者の場合
[koji:groovy]$ javap type_check | grep test
  public java.lang.Object test(java.lang.Integer);


どういった場合に型を指定するかはプログラマや状況によるとは思いますが、基本的には仮引数に関しては型を指定してあげた方が良いと思います。

12 件のコメント:

匿名 さんのコメント...

Excellent pieces. Keep writing such kind of info on your
site. Im really impressed by it.
Hey there, You have done a great job. I'll certainly digg it and in my opinion recommend to my friends. I'm sure they'll be benefited from this site.

Here is my homepage ... miu miu 財布

匿名 さんのコメント...

Genuinely no matter if someone doesn't understand afterward its up to other viewers that they will assist, so here it occurs.

Here is my website: 財布トリーバーチ

匿名 さんのコメント...

I just could not go away your website prior to suggesting that I extremely enjoyed the usual info a person provide to your visitors?
Is going to be back incessantly to check up on new posts

My webpage ... www.chloeoutletshopx.com

匿名 さんのコメント...

It's difficult to find well-informed people in this particular topic, however, you sound like you know what you're talking about!

Thanks

my web blog: chloe バッグ

匿名 さんのコメント...

I feel that is one of the so much important information for me.
And i'm satisfied studying your article. However want to remark on few basic things, The website taste is great, the articles is truly excellent : D. Good job, cheers

My site miumiuoutletshopx.com

匿名 さんのコメント...

It's perfect time to make some plans for the longer term and it's time
to be happy. I've learn this put up and if I may I desire to recommend you some fascinating issues or tips. Perhaps you can write subsequent articles relating to this article. I wish to learn even more issues approximately it!

Here is my web blog; www.hooknortonharriers.org

匿名 さんのコメント...

Good post however , I was wanting to know if you could write a litte more
on this subject? I'd be very grateful if you could elaborate a little bit more. Thanks!

Look into my web blog ... クロエ ハンドバッグ

匿名 さんのコメント...

excellent issues altogether, you simply gained a
logo new reader. What might you suggest in regards to your post that you simply made some days in the past?

Any sure?

My page ... blogspot.fr

匿名 さんのコメント...

Hi there, after reading this amazing article i am as well
happy to share my familiarity here with friends.

my web site クロエ店舗

匿名 さんのコメント...

There's definately a great deal to learn about this subject. I really like all the points you've made.


Here is my weblog :: chloe バッグ

匿名 さんのコメント...

I am sure this paragraph has touched all the internet
people, its really really pleasant post on building up
new webpage.

Feel free to surf to my webpage - louboutinshoeonline.moonfruit.com

匿名 さんのコメント...

Oh my goodness! Incredible article dude! Thank you, However I am
having problems with your RSS. I don't understand why I am unable to subscribe to it. Is there anybody else having the same RSS issues? Anyone who knows the solution will you kindly respond? Thanks!!

my page freewindows.dk