Ruby でも型チェック
動的型付け (スクリプト) 言語では、データ型のチェックが実行時にしか行われないため、プログラムの妥当性検証・デバッグといった作業が困難になります。
例えば、Ruby でプログラムを書いていて、次のようなバグに悩まされたことのある人は多いのではないでしょうか。
- Integer オブジェクトを参照しているべき変数が、他の型のオブジェクトを参照している。
- そのオブジェクトが「いつ」「どこで」代入されたものなのか分からない。
この手のバグは、問題の発生 (不正な型の代入) と発覚 (エラーの発生) の位置が離れてしまうので、非常に厄介。 発生箇所を絞り込むのが難しいため、プログラムを広範囲に渡って見直すハメになります。
check_type の導入
こうしたバグへの対処を容易にするため、私はメソッドの冒頭で引数の型をチェックするようにしています。
student.rb |
require 'date' require 'check_type' # 「学生」クラス class Student attr :id attr :fname attr :lname attr :birthday # 初期化 def initialize(id, lname, fname, birthday) @id =check_type(Integer, id, false); @lname =check_type(String, lname, false); @fname =check_type(String, fname, false); @birthday =check_type(Date, birthday, false); end end # class Stundent |
check_type.rb |
# 型チェック def check_type(type, instance, nullable =false) if (instance.nil?) unless (nullable) raise ArgumentError.new("non-nil constraint vioration") end else unless (instance.kind_of?(type)) raise(ArgumentError::new("type mismatch: #{instance.class} for #{type}")) end end return instance end |
メソッドに不正な型の引数を渡すと、ArgumentError が発生します。
test.rb |
require 'student' s =Student::new(200, 'Narita', 'Sho', '1981/07/05') |
% student.rb:20:in `check_type': type mismatch: String for Date (ArgumentError) from student:13:in `initialize' from test.rb:3:in `new' |
また、check_type
を各メソッドの冒頭に配置することで、そのメソッドがどんな型の引数をとるのか明示することにもなるため、オススメです。
関連エントリ: 配列やハッシュテーブルを構造体の代わりに使う奴はヤキ
担当: 成田 (型チェックの鬼)