teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

修正

2016/01/20 07:21

投稿

Toyoshima
Toyoshima

スコア422

answer CHANGED
@@ -1,2 +1,7 @@
1
- すいません、間違えたので修正します。
1
+
2
2
  __cloneは、複製時に呼ばれるんですね。。
3
+
4
+ なので、__clone 内部の $this はコピーされた新しいFooクラスのインスタンスですね。。。
5
+ 失礼しました。
6
+
7
+

2

修正します

2016/01/20 07:21

投稿

Toyoshima
Toyoshima

スコア422

answer CHANGED
@@ -1,1 +1,2 @@
1
- すいません、間違えたのでします。
1
+ すいません、間違えたので修正します。
2
+ __cloneは、複製時に呼ばれるんですね。。

1

間違えた

2016/01/20 07:17

投稿

Toyoshima
Toyoshima

スコア422

answer CHANGED
@@ -1,106 +1,1 @@
1
- こんにちは。
2
-
3
- __clone は、オブジェクトの複製方法を定義する関数です。
4
- かならず、同じクラスの別インスタンスを return する必要があります。
5
-
6
- おそらく実装したい__cloneメソッドの正解は以下のようになると推察します。
7
- ```PHP
8
- public function __clone(){
9
- $f = new Foo();
10
- $f->bar= clone $this->bar;
11
- return $f;
12
- }
13
- ```
14
-
15
- 例えば、次のようなクラスがあったとします。
16
- メンバ変数の $data は数値データ、 $barはBarクラスのインスタンスとします。
17
- ```PHP
18
- class Foo {
19
- private $data;
20
- private $bar;
21
-
22
- public function setData($data) { $this->data = $data; }
23
- public function getData() { return $this->data; }
24
-
25
- public function setBar($bar) { $this->bar = $bar; }
26
- public function getBar() { return $this->bar; }
27
- }
28
- ```
29
-
30
- このクラスを複製する場合、メンバ変数のdata、barもそっくりそのままコピーすべきかどうか?
31
- ・・・というのはきっと、クラスの持つ性質や使われ方によって、変わってきます。
32
-
33
- ここでは、dataはコピーするけど、barはコピーしたくないとしましょう。
34
- その場合、次のように__cloneを実装します。
35
-
36
- ```PHP
37
- class Foo {
38
- private $data;
39
- private $bar;
40
-
41
- public function setData($data) { $this->data = $data; }
42
- public function getData() { return $this->data; }
43
-
44
- public function setBar($bar) { $this->bar = $bar; }
45
- public function getBar() { return $this->bar; }
46
-
47
- public function __clone() {
48
- $f = new Foo();
49
- $f->data = $this->data;
50
- return $f;
51
- }
52
- }
53
- ```
54
-
55
- このように、__clone では
56
- $f = new Foo()
57
- で新しい自分自身のインスタンスを作り出し、それを return する必要があります。
58
-
59
-
60
- さて今度は、Barもコピーしたいとしましょう。
61
- その場合、次のcloneメソッドでは、意図するものと違う動きをする可能性があります。
62
- ```PHP
63
- public function __clone() {
64
- $f = new Foo();
65
- $f->data = $this->data;
66
- $f->bar = $this->bar;
67
- return $f;
68
- }
69
- ```
70
- なぜかというと、bar変数に入っているのは、Barクラスのインスタンスですから、
71
- 例えばこんなコードがあったとすると
72
- ```PHP
73
-
74
- $bar = new Bar();
75
- $bar->value = 1:
76
-
77
- $a = new Foo();
78
- $a->bar = $bar;
79
-
80
- $b = clone $a;
81
-
82
- $bar = $a->getBar();
83
- $bar->value = 10000;
84
-
85
- $bar2 = $b->getBar();
86
- echo $bar2->value;
87
- ```
88
- 結果は、10000です。
89
- $a の内部のBarクラスのインスタンスに加えた変化が、$b の内部のBarクラスのインスタンスにも反映されてしまいます。
90
-
91
- ```PHP
92
- $f->bar = $this->bar ;
93
- ```
94
- 複製時にこのようにしてしまうと、同じBarクラスのインスタンスを与えてしまっているためです。
95
-
96
- そのためようにします。
1
+ すいません間違えたで消します。
97
- ```PHP
98
- public function __clone() {
99
- $f = new Foo();
100
- $f->data = $this->data;
101
- $f->bar = clone $this->bar;
102
- return $f;
103
- }
104
- ```
105
- barを別のインスタンスにするために clone を使います。
106
- clone を利用する以上、Barクラスにも、__cloneの実装が必要ですが・・・。