Star Ruby の Font は実は同じ引数を与えた場合に、
同じオブジェクトが返ってくるようになっています。
Font.new("Arial", 12).eql?(Font.new("Arial", 12)) # => true
ですが、本来の Class#new の「新しくオブジェクトをアロケートする」という
性質からは異なり、直感的ではありません。
フォントは「サイズが異なるがフォントファイルは同じ」ということが
よくあり、そのために自前でキャッシュ機構を作ってしまっています。
もちろん Font.new は生成済みのオブジェクトを返すので自前で
作る必要などないのですが、つい最近までこのことを忘れていました。
これはメソッド名 new がよくないからだと考えられます。
そこで、以下を提案します。
1. Font.[] (仮) メソッドを追加 (引数は今の Font.new と同じ)
2. Font.new メソッドを撤廃
2. にいきなりいくのは、後方互換性を考えると無茶なので保留しますが、
何かご意見ございましたらよろしくお願いします。
(実は Color も同じなのですが、これは保留。)
--
Hajime Hoshi <hajim...@gmail.com>
>> ですが、本来の Class#new の「新しくオブジェクトをアロケートする」という
>> 性質からは異なり、直感的ではありません。
>>
>> フォントは「サイズが異なるがフォントファイルは同じ」ということが
>> よくあり、そのために自前でキャッシュ機構を作ってしまっています。
>> もちろん Font.new は生成済みのオブジェクトを返すので自前で
>> 作る必要などないのですが、つい最近までこのことを忘れていました。
>> これはメソッド名 new がよくないからだと考えられます。
>
> 最近、私も気になり始めてました。毎フレーム実行するような処理の中にnewを書くのは、確かに気持ちが悪いです(フォントなんていう、リソースを外部
> から持ってくるようなものはなおさら)。
やはりそうですよねぇ。
>> そこで、以下を提案します。
>>
>> 1. Font.[] (仮) メソッドを追加 (引数は今の Font.new と同じ)
>> 2. Font.new メソッドを撤廃
>
> Timeクラスのインスタンス生成には、newメソッドとnowメソッドが使えたと思います。後者はとても直感的ですよね。Font.makeとかでも
> よさそうですが、二度目以降は同じオブジェクトが、同じ内容で返ってくるわけで、ちょっと語弊があるかな。Font.recruit? むーん。new
> メソッドは、無理に撤廃する必要はないんじゃないでしょうか。
Time.new は object_id を見ると毎回オブジェクトをアロケートしているようなので、
そのメソッド名で全く問題ないですね。
あとは Font.get とか。うーむ。
あと考えたのですが、 Font クラスをいっそのことなくしてしまい、
フォント名とサイズを Texture#render_text に渡すようにするとかどうでしょう。
ボールドとイタリックがどうするかまだ分かりませんが。
>> (実は Color も同じなのですが、これは保留。)
>
> たとえば、連続的に値が変化する大量のColorオブジェクトを使い、なめらかな色の変化を表現したい場合って、結構多いと思います。キャッシュ機能は
> Fontと比べて、使う機会があるのではないでしょうか。
Color.new も Font.new と同様にキャッシュしたものを返しえます。
ドキュメントには明記していないですがそういう実装になっています。
Color は最低 4bytes の値を保持するだけのオブジェクトであり、
Font のように内部で得体のしれない何かをつくるオブジェクトではないので、
new しまくってもそんなに問題ないと考えています。
--
Hajime Hoshi <hajim...@gmail.com>
>> Time.new は object_id を見ると毎回オブジェクトをアロケートしているようなので、
>> そのメソッド名で全く問題ないですね。
>>
>> あとは Font.get とか。うーむ。
>>
>> あと考えたのですが、 Font クラスをいっそのことなくしてしまい、
>> フォント名とサイズを Texture#render_text に渡すようにするとかどうでしょう。
>> ボールドとイタリックがどうするかまだ分かりませんが。
>
> フォント名とサイズをTexture#render_text に渡すとなると、素直に考えれば、引数を増やすことになりますよね。さらにイタリックや
> ボールドがからんでくると、引数が増えすぎる気がします(StarRuby的にはオプションにもなり得るか。それでも入力事項が増える事に変わりな
> い)。Texture#render_text は、現行でも引数が多いメソッドですから、あまり歓迎はできないですかねえ。
たしかにそうですね。
オプションの引数増やすのも、フォントは最後の引数ではないので
分かりにくくなりそうです。
bold や italic についてですが、あまりにも使われてないなら
いっそのこと撤廃しようかなとも思いました。
(Daigo くんには反対されましたが。)
> あと、これはあくまで個人的な考えなんですが、フォントに関しては、確かにサイズ違いのものを使いたい場合が多いですが、それでも数種あれば、大抵の場
> 合、事足りてしまうように思います。それなら、いちいちフォント名とファイルサイズのセットで毎回指定して持ってくるより、インデクスやハッシュのキー
> のように、一オブジェクト対一オブジェクトの関係性でアクセスできたほうが便利かなあと思うのです(それこそ、自前のモジュールなりなんなりを作ればい
> い話ですね)。
なるほど。
>> Color.new も Font.new と同様にキャッシュしたものを返しえます。
>> ドキュメントには明記していないですがそういう実装になっています。
>>
>> Color は最低 4bytes の値を保持するだけのオブジェクトであり、
>> Font のように内部で得体のしれない何かをつくるオブジェクトではないので、
>> new しまくってもそんなに問題ないと考えています。
>
> なるほど。
> 「返しえます」ということは、返らない場合もあるということでしょうか。GCに拾われる?
まず、キャッシュにそもそも保存されていない Color オブジェクトを取得しようとした場合は、
新しく生成されます。
また、キャッシュの量に制限があるのですが、それを超える種類の Color オブジェクトを
生成しようとすると、キャッシュにある Color オブジェクトの一番古いものが
キャッシュから削除されます。
なので、一度キャッシュから取得した Color でも、次におなじ引数で new するときは
違う Color オブジェクトになっている可能性があります。
--
Hajime Hoshi <hajim...@gmail.com>