1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Kotlinでpythonのデコレータを再現したい

Posted at

背景

Kotlinでコード書いてる時Pythonで言うところのデコレータを使いたかったが、検索しても見つけられませんでした。
クラス委譲というものが出てきましたが、コレジャナイ感。
C系とjava系だからそんなものかと思いつつ、とりあえず書いてみたという話です。

補足 デコレータって?

関数やクラスを文字通り「装飾」する機能のこと。これにより既存の関数やクラスの中身を直接触らず、その外側から機能を追加したり書き換えたりすることができる。
詳しくはこの記事を見てください。

Pythonのデコレータの例

さっき貼った記事のコードと同じです。

コード

decorater.py
#デコレータを定義
def greet(func):
    def inner(*args,**kwargs):
        print("こんにちは。")
        result = func(*args,**kwargs)
        print("よろしくお願いします。")
        return result
    return inner
#使い方
@greet
def myName(name):
    print(f"私は{name}です。")
    return "挨拶 終"
    
print(myName("ねこでべろん"))

デコレータによって装飾された引数をとる新たな関数が返され、それを引数付きで実行することで結果を得ています。

結果

こんにちは。
私はねこでべろんです。
よろしくお願いします。
挨拶 終

kotlinで再現

とりあえず素直に書き変えようとすると、、、

fun <R> greet(func:(funcの引数の型)->R):(funcの引数の型)->R{
}

無理です。
funcの引数の型は引数の個数も種類もこの時点では決まってないので書けません。
種類が決まっていないのは対応できますが、数が決まっていないのがきついです。可変長引数も使って試行錯誤してみましたが私には無理でした。
諦めて少しロジックを変えます。

コード

//デコレータを定義
fun <T> greet(func:()->T):()->T{
    fun wrapper():T{
        println("こんにちは。")
        val result = func()
        println("よろしくお願いします。")
        return result
    }
    return ::wrapper
}
//デコレータに渡すための処理
fun myName(name:String):String{
    //実際の処理
    fun _myName():String{
        println("私は${name}です。")
        return "挨拶 終"
    }
    return greet(::_myName)()
}

fun main() {
   println(myName("ねこでべろん"))
}

引数が邪魔なので、デコレータに与える関数を引数に特化させます。
デコレータからは引数に特化しかつ装飾された関数が返ってきます。
これを実行することで結果が得られるというわけです。
実行部分だけ見れば似ていますが、内部的には全然違います。

結果

こんにちは。
私はねこでべろんです。
よろしくお願いします。
挨拶 終

一般化

とりあえず載せます。

//デコレータ
fun <T> decorater(func:()->T):()->T{
    fun wrapper():T{
        ToDo()
        val result = func()
        ToDo()
        return result

    }
    return ::wrapper
}
//関数
//Typeは同じ型
fun function(arguments):Type{
    fun _function():Type{
        ToDo(arguments)
        return result
    }
    return decorater(::_function)()
}

最後に

今回はPythonのデコレータを再現してみました。
完全再現という訳には行かなかったのが少し悔しいです。
Pythonが動的型付け、Kotlinが静的型付けということでやはり型で苦労しましたね。
完成したものも各方面から怒られそうですが、その方々には加筆してもらうつもりです。
記事の内容に誤りがあればコメントや加筆等よろしくお願いします。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?