SlideShare a Scribd company logo
明日からちょっと
KotlinでAndroidが書きたくなる(かもしれない?)
SAM変換と拡張関数
 
室星亮太
2014/7/4(金))第2回)かわいいKotlin勉強会)#jkug
突然ですが質問です!
Kotlin書いたことある方?
「Kotlin'書いたことない」
ってイベントページに書いたけれど
本当は書いたことある方?
Androidアプリ
開発したことある方?
ありがとうございました!
お前だれよ
• 名前":"室星亮太
• 仕事":"Androidアプリ開発(Java)、Unityゲーム開発(C#)
• Twi6er":"@RyotaMurohoshi
• 投稿先":"h6p://qiita.com/RyotaMurohoshi
• 興味":"Kotlin,"Groovy,"C#,"Unity,"SonyのWearable"Device
AndroidアプリをJavaで開発していて、
「なんでこんなに冗長なコードが必要なんだ!」
ってイラっとすることはありませんか?
私はあります!
C#を業務で使い始めたりしたり、
Groovyをほんのちょっと勉強したら、
「なんでJava、〇〇できないのー!」
って、イラッとなりました
そこでKotlinですね!
明日からちょっと
KotlinでAndroidが書きたくなる(かもしれない?)
SAM変換と拡張関数
と題して今日はLTします!
いらっとする冗長なコード1
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.v(TAG, "clicked");
}
});
どんなAndroid入門書にも載っている、アクティビティでよくみるコード
Kotlinで書いたやつと比べると、冗長なのが一目瞭然!
Kotlinだとすっきり
button.setOnClickListener { Log.v(TAG, "clicked") }
Java、Kotlinそれぞれのクリックリスナー
Kotlin
button.setOnClickListener { Log.v(TAG, "clicked") }
Java
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.v(TAG, "clicked!");
}
});
行数が短くなったことではなく、
「冗長な部分は書く必要がなく
本質的なことだけ書けばよくなった」
というのがミソ
Javaのコードをもう一度見てみましょう
button.setOnClickListener(new View.OnClickListener() { // new以降本質じゃない
@Override // <- 本質じゃない
public void onClick(View v) { // <- 本質じゃない
Log.v(TAG, "clicked!");
} // <- 本質じゃない
}); // <- 本質じゃない
Javaは本質じゃない部分が多い。Kotlinは本質のみを記述すればいい
Kotlinはなぜあんな記述ができるのか?
Single'Abstract'Method'Conversions
SAM変換
h"p://blog.jetbrains.com/kotlin/2013/08/kotlin;m6;is;here/
SAM$インターフェース
一つの(Single))抽象(Abstract))メソッド(Method)
をもつインターフェース
• Runnable):)void)run()
• View.OnClickListener):)void)onClick(View)v)
• Response.Listener<T>):)void)onResponse(T)response))
など、他にもたくさん
SAM変換
関数リテラル!">!SAMインターフェース!な変換
Kotlinでは、SAMインターフェースを引数にとるメソッドで、
引数の型と順序そして返値型が一致する関数リテラルを渡すと
インターフェースに変換してくれる
SAMインターフェースが必要な所も、関数リテラルでスッキリ!
SAM変換できる例
button.setOnClickListener( { (v : View): Unit -> Log.v(TAG, "clicked") })
button.setOnClickListener( { v -> Log.v(TAG, "clicked")})
button.setOnClickListener{ v -> Log.v(TAG, "clicked") }
button.setOnClickListener{ Log.v(TAG, "clicked") }
val listener : (View) -> Unit = {v -> Log.v(TAG, "clicked") }
//or
val listener : (View) -> Unit = { Log.v(TAG, "click") }
//or
val listener = { (v : View) : Unit -> Log.v(TAG, "clicked") }
button.setOnClickListener(listener)
SAM変換できない例
// 下記はコンパイルエラー
// Type mismatch
val listener : View.OnClickListener = { (v : View) : Unit -> Log.v(TAG, "clicked") }
// 下記は実行時エラー
// java.lang.ClassCastException
val listener = { (v : View) : Unit -> Log.v(TAG, "clicked") } as View.OnClickListener
引数に関数リテラルを渡さないといけない
SAM変換で無駄コードを無くせますね!
もう一例
VolleyのStringRequest
VolleyのStringRequest0Java版
StringRequest request = new StringRequest(
"https://www.google.co.jp/",
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Toast.makeText(getApplicationContext(), response, Toast.LENGTH_LONG).show();
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(getApplicationContext(), "onErrorResponse", Toast.LENGTH_LONG).show();
}
}
);
無駄な部分が多く、縦に長い...
VolleyのStringRequest0Kotlin版
val request = StringRequest(
url = "https://www.google.co.jp/",
listener = { response ->
Toast.makeText(this, response, Toast.LENGTH_LONG).show()
},
errorListener = { volleyError ->
Toast.makeText(this, "onErrorResponse", Toast.LENGTH_LONG).show()
}
);
型パラーメータがあるインターフェースもSAM変換可能
名前付き引数で可読性アップ
ちょっとGroovyもみてみましょう
GroovyもSAM変換が使えるようです。
button.setOnClickListener { v -> Toas.makeText(this, "click", Toast.LENGTH_LONG).show() }
Groovy&2.2からas演算子がいらなくなったそうです。
h"p://groovy.codehaus.org/Groovy+2.2+release+notes
ちょっとGroovyもみてみましょう
SAMインターフェースだけでなく、複数メソッドを持つインターフェースも
Map+クロージャー+as演算子でこんな感じに!
viewPager.setOnPageChangeListener ([
onPageScrollStateChanged: { state -> Log.v(TAG, state) },
onPageScrolled : { position, positionOffset, positionOffsetPixels -> /*略*/ },
onPageSelected : { position -> Log.v(TAG, position) }
] as ViewPager.OnPageChangeListener)
h"p://groovy.codehaus.org/Groovy+way+to+implement+interfaces
実はAndroidStudioとIntelliJだと
一つだけメソッドを実装した匿名クラスがいい感じに!(SAM型も)
button.setOnClickListener((v) -> {Log.v(TAG, "clicked");});
IDE上ではいい感じで折り畳まれてますが、
githubとかでコードリビューするときは、
ほら畳まれないし...
h"p://qiita.com/RyotaMurohoshi/items/0ce799c747d91756131a
以上
SAM変換でした。
いらっとする冗長なコード2
ImageView imageView = (ImageView)findViewById(R.id.image_view);
どんなAndroid入門書にも載っている、アクティビティでよくみるコード
けれど「ImageView」ってなんで2回書く必要あるん?型推論してくれてもいいじゃん!
とりあえず継承します?
Ac#vityを継承したクラスBaseAc#vityにて、こんなメソッド定義すれば、
public <T extends View> T findById(int viewId) {
return (T)findViewById(viewId);
}
BaseAc'vityを更に継承したクラスでは、こんな感じでキャスト不要になりますね
ImageView imageView = findById(R.id.image_view);
けど継承って
• 継承むずい
• 「継承が許されるのは小学生までだよね」、だと...
• Ac$vityのサブクラスいくつかあるけど、全部に更にサブクラス
作ってメソッド定義する?
ちょっとないかな...
さてどうしましょう?
• 冗長な記述が頻発したり、よく使う処理がある
• Ac$vityとかに、メソッドを追加したい!
• けど継承したくない)or)できない
Extension)Funcitons
拡張関数
h"p://confluence.jetbrains.com/display/Kotlin/Extension+func=ons
Extension)Funcitons(拡張関数)とは
• 継承せずにメソッドを追加できる"
• 継承禁止なクラスにもメソッドを追加できる
• privateなメンバにアクセスはできない
• メソッドをオーバーライドはできない
Extension)Func-onsの例)定義側
extensions.kt内にて
package com.mrstar.extensions
import android.app.Activity
import android.view.View
fun <T : View> Activity.findById (id : Int) : T = findViewById(id) as T
Extension)Func-onsの例)利用側
package com.mrstar.android_with_kotlin
// 略
import com.mrstar.extensions.findById // <- 注目
public class MainActivity() : FragmentActivity() { // <- 注目
protected override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView: ImageView = findById (R.id.image_view) // <- 注目
}
}
• fun$ClassName.methodName(hoge$:$Hoge)$:$Fuga"みたいな感じで
メソッドを定義します
• 定義した拡張メソッドをimportします
• そうすると普通のメソッドのように使えます
• この例だとAc+vityのサブクラスだけでなく、
FragmentAc+vity、Ac+onBarAc+vity、他のサブクラスでも使え
ます(継承で定義するなら、各クラスにメソッド定義が必要)
Extension)Func-onsを使えば...
• 継承しなくてもメソッドを追加できますね
• たくさんのクラスにメソッドを追加しなくてもいいですね
• 自作のメソッドで冗長な記述をスッキリできますね!
ちょっとC#もみてみましょう
C#にも拡張関数と同じような拡張メソッドがあります。
// 定義側
public static class StringExtensions
{
public static string Decorate(this string str, string symbol) {
return string.Format("{0}{1}{2}", symbol, str, symbol);
}
}
//利用側
string decoratedMessage = "Hello!".Decorate("===")
こんな感じで、sta$cなクラスにsta$cなメソッドとして拡張メソッドを定義します。
ちょっとC#もみてみましょう
C#は
• Javaのpackageアクセスのような、メンバを同じ名前空間だけに
公開するという制限がない
• privateでsta.cな入れ子のクラスは作れる
• が↑なクラスでは拡張メソッドを定義できない
このクラスにだけ、この名前空間でだけ使えるという拡張メソッドを定義できない!
一方Kotlinでは
• packageにその名前空間とそのサブ名前空間限定で
• クラス内にprivateアクセスレベルで
• 関数内にローカル関数内として、ローカルスコープで
Kotlinだと拡張関数を定義できる!
以上
拡張関数でした。
質問ありますか?
ご清聴ありがとうございました!
 
SAM変換について(Qiita)
h"p://qiita.com/RyotaMurohoshi

More Related Content

PPTX
Hubotを使ってbotをつくろう!
PDF
SIerアーキテクト視点でみたKotlinの紹介
PDF
KotlinでROSノードを書いてみた
PDF
Kotlinソースコード探訪
PDF
とある現場のシステムアーキテクチャ
PPTX
PDF
kotlinについて
PDF
Kotlinで快適Android開発 #W8lt
Hubotを使ってbotをつくろう!
SIerアーキテクト視点でみたKotlinの紹介
KotlinでROSノードを書いてみた
Kotlinソースコード探訪
とある現場のシステムアーキテクチャ
kotlinについて
Kotlinで快適Android開発 #W8lt

Viewers also liked (9)

PDF
もう一度Kotlinの話をしよう #ndsmeetup4
PDF
Kotlinあるある言いたい
PDF
Kotlinでマッチョする話
PDF
Kotlin: Why Do You Care?
PDF
UnityでC#6.0が使える未来がそろそろ来そう!
PDF
minne の API 改善
PDF
普段C#を使っている僕から見たKotlin
PDF
Jvm言語とJava、切っても切れないその関係
PDF
Android学ぶを君へ。生き抜くためのナレッジ共有
もう一度Kotlinの話をしよう #ndsmeetup4
Kotlinあるある言いたい
Kotlinでマッチョする話
Kotlin: Why Do You Care?
UnityでC#6.0が使える未来がそろそろ来そう!
minne の API 改善
普段C#を使っている僕から見たKotlin
Jvm言語とJava、切っても切れないその関係
Android学ぶを君へ。生き抜くためのナレッジ共有
Ad

Similar to 明日からちょっと KotlinでAndroidが書きたくなる(かもしれない?)SAM変換と拡張関数 (18)

PDF
かわいいKotlinでAndroidアプリをつくろう
PDF
Kotlin勉強会 in ehime
PDF
KotlinAndroidLibを使ってみた
PDF
Kotlinアンチパターン
PPTX
Java で書かれたAndroid アプリに Kotlin を適用させていく
PPTX
ミクシィ 21卒向け Android研修
PDF
3分で作る Kotlin Friendly な API
PPTX
Kotlin 使いになりました
PDF
20170618 Google I/O報告会in福岡
PPTX
Java で書かれた Android アプリに Kotlin を適用させていく
ODP
OSC2011 Androidハンズオン
PDF
Potato03 KotlinでAndroidアプリ開発(後編)
PDF
Kotlinにお触り
PPTX
DroidKaigi アプリの内部を見る
PPTX
Kotlin が公式サポートになったので Kotlin の話
PDF
ScalaでAndroidアプリ開発
PPTX
モダンなAndroidアプリ開発勉強会
PDF
Refactoring point of Kotlin application
かわいいKotlinでAndroidアプリをつくろう
Kotlin勉強会 in ehime
KotlinAndroidLibを使ってみた
Kotlinアンチパターン
Java で書かれたAndroid アプリに Kotlin を適用させていく
ミクシィ 21卒向け Android研修
3分で作る Kotlin Friendly な API
Kotlin 使いになりました
20170618 Google I/O報告会in福岡
Java で書かれた Android アプリに Kotlin を適用させていく
OSC2011 Androidハンズオン
Potato03 KotlinでAndroidアプリ開発(後編)
Kotlinにお触り
DroidKaigi アプリの内部を見る
Kotlin が公式サポートになったので Kotlin の話
ScalaでAndroidアプリ開発
モダンなAndroidアプリ開発勉強会
Refactoring point of Kotlin application
Ad

More from Ryota Murohoshi (16)

PDF
【Unity】気づいたら加わっていたあいつ【もくもく】
PDF
【ハピバ】未来に備えたKotlin、大好きだぜ!【Kotlin 1.0】
PDF
「var禁止」禁止
PDF
Javaのバージョニング問題の話しよっか
PDF
LINQ、Select連弾ってやります?
PDF
C#のList_TがIListを実装している件
PDF
どうしてこのコードエラーになるんですか?
PDF
広告ネイティブプラグインの辛かった話しよっか
PDF
UnityでC#を勉強しはじめた私の主張
PDF
T4使ってみた
PDF
UnityでのLINQ活用例
PDF
私とUnityとLINQと
PDF
「LINQ」っていう名前だけでも 覚えて帰ってください!
PDF
JXUGのLTだけれどもUnity+iOS+LINQの話をしようと思う!
PDF
RxJava初心者の私が良いと思ったやり方、素敵だと思った資料など
PDF
共変戻り値型って知ってますか?
【Unity】気づいたら加わっていたあいつ【もくもく】
【ハピバ】未来に備えたKotlin、大好きだぜ!【Kotlin 1.0】
「var禁止」禁止
Javaのバージョニング問題の話しよっか
LINQ、Select連弾ってやります?
C#のList_TがIListを実装している件
どうしてこのコードエラーになるんですか?
広告ネイティブプラグインの辛かった話しよっか
UnityでC#を勉強しはじめた私の主張
T4使ってみた
UnityでのLINQ活用例
私とUnityとLINQと
「LINQ」っていう名前だけでも 覚えて帰ってください!
JXUGのLTだけれどもUnity+iOS+LINQの話をしようと思う!
RxJava初心者の私が良いと思ったやり方、素敵だと思った資料など
共変戻り値型って知ってますか?

明日からちょっと KotlinでAndroidが書きたくなる(かもしれない?)SAM変換と拡張関数