Juliaのデストラクター
Juliaのマニュアルを読むとコンストラクターの記述はちゃんとあるのですが、デストラクターに関しての記述が見当たりません。ググっても情報が出てこないようなので、ここにその方法を残しておきます。
JuliaにはC++の~ClassName()
のようにデストラクター専用の関数はありませんが、コンストラクターの中でオブジェクトがGCされたときの処理を記述できます。
やり方は簡単で、Base.finalizer()
関数がまさにオブジェクトが破壊された時の処理を登録するための関数ですので、これを使うわけです。
finalizer(x, function)
はx
が到達不可能になったときにfunction(x)
を呼ぶ仕組みになっているため、function
に資源を解放するような処理を置いておけば良いことになります。
何かDBなどとの接続を管理する型Connection
の例で考えてみると、以下のように何かmallocなどの直後にfinalizer()
で後処理を登録すればいいことになります。
type Connection conn::Ptr{Void} open::Bool function Connection() this = new(c_malloc(sizeof_connection_info), false) finalizer(this.conn, connection_finalizer) err = ccall( (:connection_init, "libsomedb"), Cint, (Ptr{Void},), this.conn ) if err != 0 error("failed to create a new connection") end this.open = true this en
Juliaのソースで実際に使われている例を見てみましょう。
正規表現のライブラリで確保したメモリへのポインタをfinalizer()
で開放しています。
type Regex pattern::ByteString options::Uint32 regex::Ptr{Void} extra::Ptr{Void} function Regex(pattern::String, options::Integer) pattern = bytestring(pattern) options = uint32(options) if (options & ~PCRE.OPTIONS_MASK) != 0 error("invalid regex options: $options") end re = compile(new(pattern, options, C_NULL, C_NULL)) finalizer(re, function(re::Regex) re.extra != C_NULL && PCRE.free_study(re.extra) re.regex != C_NULL && PCRE.free(re.regex) end) re end end
https://github.com/JuliaLang/julia/blob/0f54ca52e350c89d821069cbdc349f1e49e43cbc/base/regex.jl#L7-27
注意する点としては、
finalizer()
はimmutableな型には適用できない- コンストラクターでは最後に自分自身を返すことを忘れない
ことが挙げられます。
参考