Ruby ARGFのクラス名がおかしい
概要
これは汚いバグですか?
km@latika:~$ ruby -v -e 'puts nil.class.to_s, ARGF.class.to_s'
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux-gnu]
NilClass
ARGF.class
km@latika:~$ jruby -v -e 'puts nil.class.to_s, ARGF.class.to_s'
jruby 9.3.9.0 (2.6.8) 2023-01-16 9.3.9.0+ds-8 OpenJDK 64-Bit Server VM 17.0.10+7-Debian-1deb12u1 on 17.0.10+7-Debian-1deb12u1 +jit [x86_64-linux]
NilClass
ARGFClass
ピリオドを含むクラス名を他で見たことがありません…
解決策
これはバグではありません。クラスはその珍しい名前で明示的に作成されています。 io.c から:
rb_cARGF = rb_class_new(rb_cObject);
rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
rb_cARGF はクラスオブジェクトであり、rb_set_class_path はそれを「ARGF.class」という名前で登録します。これは C でのみ可能であり、Ruby 内からそのようなクラスを作成することはできません。
ARGF.class の別のインスタンスを作成することはほとんど意味がないため、ARGF のクラスを通常のクラスとして公開したくなかったのかもしれません。事前に定義されたインスタンス ARGF と対話することのみが想定されています。
ピリオドは任意ではないことに注意してください。ピリオドによってクラス名が有効な Ruby 式になります。ARGF.class と入力すると、実際にはそのクラスに解決されます。非常に適切です。
コードベースによれば、これがその種の唯一のクラス名ですが、有効な定数名ではない名前を持つクラス/モジュールの例は他にもあります。
例外のサブクラスである致命的:
Exception.subclasses
#=> [..., SignalException, fatal, SystemExit]
generic_readable および generic_writable は、IO の下の StringIO によって定義されます。これらは StringIO に含まれています。
require 'stringio'
StringIO.ancestors
#=> [StringIO, IO::generic_writable, IO::generic_readable, ...]
C で (そうでない場合) 無効な定数/クラス名を使用すると、オブジェクトを Ruby で定数として解決できなくなります。IO::generic_writable を試行すると、それを (存在しない) メソッドとして呼び出そうとし、IO.const_get( :generic_writable) は NameError を発生させます。