オブジェクトとしての一意性
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
メソッドは該当する値のオブジェクトを取り除き、取り除かれたオブジェクトを返す。