This page looks best with JavaScript enabled
⚠️

【Ruby】オブジェクトの一意性について

 ·   ·  ☕ 2 分で読めます
✏️

オブジェクトとしての一意性

Rubyでは全てがオブジェクトである。
そのため、同じオブジェクトに対してそのものを変形するような処理を行うと、同期することになる。

1
2
3
4
5
6
irb(main):046:0> foo = 'foo'
irb(main):047:0> foo2 = foo
irb(main):050:0> foo.capitalize!
=> "Foo"
irb(main):051:0> foo2
=> "Foo"

同じオブジェクトには同一のobject_idが振られている。
同じオブジェクトかどうかはequal?メソッドで確かめることができる(object_idが等しいかどうか)。
===はオブジェクトのを比較しているだけ。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
irb(main):054:0> foo3 = 'Foo'
irb(main):055:0> foo === foo3
=> true
irb(main):056:0> foo.equal?(foo3)
=> false
irb(main):057:0> foo.equal?(foo2)
=> true
irb(main):058:0> foo.object_id
=> 240
irb(main):059:0> foo2.object_id
=> 240
irb(main):060:0> foo3.object_id
=> 260

=による値の変化

1
2
3
4
5
6
7
irb(main):008:0> a = 'a'
irb(main):009:0> b = a
irb(main):010:0> a.equal?(b)
=> true
irb(main):011:0> b = 'b'
irb(main):012:0> a.equal?(b)
=> false

=はオブジェクトの変形ではなく、別オブジェクトの再代入である。

cloneによる別オブジェクト化

#cloneによって、そのものとは別の同じ値を持つオブジェクトとしてコピーができる。
しかし、Arrayオブジェクトに対する#cloneでは複製できるのはArrayのみで、中身は同じオブジェクトになってしまう。shallow copy(浅いコピー)

1
2
3
4
5
6
irb(main):001:0> a = ['a', 'b', 'c']
irb(main):002:0> b = a.clone
irb(main):003:0> a.equal?(b)
=> false
irb(main):004:0> a[0].equal?(b[0])
=> true

#clone#dupの違いは以下参照。まあどっちも浅い。
Object#clone (Ruby 2.7.0 リファレンスマニュアル)

ActiveSupportを読み込めば、#deep_dupで深いコピーができる。
または、Marshalを用いて文字列として展開した後に再度配列化することで、まるごと別オブジェクトにすることができる。

deleteメソッドの挙動

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
irb(main):005:0> a = 'a'
irb(main):006:0> b = 'b'
irb(main):007:0> c = 'c'
irb(main):008:0> array = [a, b, c]
irb(main):009:0> c2 = 'c'
irb(main):010:0> c.equal?(d)
=> false
irb(main):013:0> array.delete(c2).object_id
=> 180
irb(main):014:0> c2.object_id
=> 200
irb(main):015:0> c.object_id
=> 180

deleteメソッドは該当する値のオブジェクトを取り除き、取り除かれたオブジェクトを返す。

Share on

END
END
@aiandrox

 
目次