Rubyの明示的/暗黙的な型変換についてのメモ(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

Rubyの明示的/暗黙的な型変換についてのメモ(翻訳)

自分用にメモ。

Rubyには型強制(type coercion)メソッドがいくつもペアになっています。

  • to_ito_int
  • to_sto_str
  • to_ato_ary
  • to_hto_hash

右と左はいったい何が違うのでしょうか?どういうときに使い、どんなときに実装するのでしょうか?

短い方は明示的な変換です。

  • (integerやstringやarrayといった)何らかの型に変換される可能性がある場合は、その型に明示的な変換を実装すべき
  • 何らかの意味のある型に変換されることを期待するのであれば、受け取るデータに対してこれらのメソッドを呼び出すべき

長い方は暗黙的な変換です。

  • 型が自分自身を「kind of」に該当する型(よりよい、または特殊なnumber、string、array、hash)に変換されるとみなす場合にのみ、暗黙的な変換を実装すべき
  • 変換後の型について厳密な要求がある場合は、受け取るデータに対してこれらのメソッドを呼び出すべきだが、クラスの比較ではなくダックタイピングによるRubyらしい方法でチェックしたいと思うのが普通
  • それ以外の場合にこのメソッドを実装したり呼んだりすることはまかりならぬ

Rubyの演算子やコアメソッドは、データを暗黙的に変換します。

  • "string" + other#to_str on otherを呼び、[1,2,3] + other#to_aryを呼ぶなど(オブジェクトがこのメソッドに応答しない場合はTypeError: no implicit conversionを返す)
  • "string" * other[1,2,3] * other#to_int on otherを呼び出す
  • a, b, c = *otherother#to_aryを呼ぶ(そして独自のコレクションオブジェクトを”unpack”するのに使われるが、otherto_aryを実装していると思わぬ振る舞いを見せることがある: しかしこれはコレクションではないと考えられる)
  • some_method(*other)は上と同様にother#to_aryを使う
  • some_method(**other)(Ruby 2で登場)はother#to_hashを使う

何度でも言います。自分のやっていることを把握できていないのであれば、暗黙の変換を決して実装してはなりません。たとえば#to_hashが実装されている(#to_hよりはイケてる名前だから?)ために奇妙極まる振る舞いが発生する事例をあちこちで目にします。

実用的な例をご覧いただきましょう。

class Dog
  attr_reader :name, :age
  def initialize(name, age)
    @name, @age = name, age
  end

  # シリアライズをto_hではない方法で定義するのは誤り
  def to_hash
    {species: 'Dog', name: name, age: age}
  end
end

def set_options(**some_options)
  p some_options
end

dog = Dog.new('Rex', 5)

set_options(foo: 'bar')
# {foo: 'bar'}が出力される、よしよし

set_options(1)
# この呼び方はできない: ありがたいArgumentErrorが発生

set_options(dog)
# なぬ?dogがオプションハッシュとして扱われて
# {species: 'Dog', name: name, age: age}が出力された

require 'awesome_print' # pretty print(pp)に使われる人気gem
ap dog
# のぉぉぉ!Dog#inspectじゃなくてハッシュのppメソッド呼んでるし

以下もご覧ください。

関連記事

Ruby: 自分のクラスに`#to_a`を実装すべきじゃない(翻訳)

Ruby 2.5の`yield_self`が想像以上に何だかスゴい件について(翻訳)

Ruby: 「マジック」と呼ぶのをやめよう(翻訳)

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の半分ほど、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れてそれぞれ一部を翻訳。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好き。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

BigBinary記事より

ActiveSupport探訪シリーズ