[ruby-list:50845] Re: Stringの派生オブジェクトにsubを取った時のインスタンス変数のコピー
From:
MASAKI Haruka <yek@...>
Date:
2019-11-21 17:32:05 UTC
List:
ruby-list #50845
正木です。
String#subは自身を返すわけではありませんから、
戻り値となっているオブジェクトはsubを呼び出したオブジェクトとは別物ですので、
インスタンス変数は共有されません。
サブクラスではなく、特異クラスを使った場合でも違うオブジェクトなので、
特異クラスは持っていない状態になります。
#!ruby
str = "Hello"
class <<str
@foo = "foo"
def foo
@foo
end
end
str.foo # foo
str2 = str.sub("foo", "bar")
str2.foo # error
varの値を継承したいなら次のようにするのはいかがでしょう。
class NString < String
#...
def var=(val)
@var = val
end
def sub
new_nstr = super
new_nstr.var = @val
new_nstr
end
end
On Fri, 22 Nov 2019 01:55:42 +0900
Takefumi URA <ura.takefumi@gmail.com> wrote:
> 浦といいます。
>
> Stringを派生させたクラスのオブジェクトにインスタンス変数を設定しました。
> このオブジェクトにsubを適用してできたオブジェクトにはそのインスタンス
> 変数がコピーされていませんでした。以下のような感じです。
>
>
> $ cat test-string.rb
> class NString < String
> def initialize(s)
> @var = s.hash # ハッシュ値を取ってるのは特に意味はない
> super s
> end
>
> def inspect
> "#<NString:#{@var}:#{self}>"
> end
> end
>
> ns = NString.new('abc')
> p ns # => #<NString:val:abc>
> p ns.sub(/a/, 'A') # => #<NString::Abc>
>
> $ ruby -v test-string.rb
> ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin18]
> #<NString:3775343761872790250:abc>
> test-string.rb:8: warning: instance variable @var not initialized
> #<NString::Abc>
>
> ご覧の通り @var が引き継がれておらず初期化もなされていません。
> このあたり、インスタンス変数もケアしてくれる (subでcloneなりdupなりやってる)
> のかなと思っていたので少し意外でした。
>
> Stringのソースを見てないのでなんともなんですけど、
> subを取って新たなオブジェクトが得られた時 @var の値をコピーするにはどうしたらよいでしょうか?
>
> 別解としてsub!を使ってそもそもコピーする必要をなくすというのはあるでしょうけど
> (というかそれでとりあえず解決しました)、純粋に疑問に思ったので質問してみることにしました。
>