回答編集履歴

2

誤字の修正と追記

2016/12/21 21:16

投稿

raccy
raccy

スコア21735

test CHANGED
@@ -48,7 +48,11 @@
48
48
 
49
49
 
50
50
 
51
- 最後に、上を修正してPersonを不変負ぶえ区と似しても、そのサブクラスは同じく不変オブジェクトであるは限りません。Person型とされる物は全て不変と扱ってはいけないと言うことです。これを防ぐには同じくPersonクラス自体をfinalにする必要があるでしょう。その意味では、少し片手落ちのような気もします。
51
+ 最後に、上を修正してPersonを不変オブジェクトにしても、そのサブクラスは同じく不変オブジェクトであるは限りません。Person型とされる物は全て不変と扱ってはいけないと言うことです。これを防ぐには同じくPersonクラス自体をfinalにする必要があるでしょう。その意味では、少し片手落ちのような気もします。
52
+
53
+
54
+
55
+ このように、全てがfinalなフィールドであることは不変オブジェクトの十分条件でも必要条件でもありません。ただ、もし、不変オブジェクトであれば、全てのフィールドをfinalにしてもコンパイルエラーが起きないはずです。間違って不変オブジェクトでは無くなってしまっていることを検知するためにfinalに設定することは無駄ではありません。
52
56
 
53
57
 
54
58
 

1

不変オブジェクトについて追記・修正

2016/12/21 21:16

投稿

raccy
raccy

スコア21735

test CHANGED
@@ -8,11 +8,11 @@
8
8
 
9
9
 
10
10
 
11
- staticではないフィールドにprivateを設定するとコンストラクタでしか代入できなくなります。全てがfinalなフィールのオブジェクトは**不変(immutable)**オブジェクトともいわれ、関数型プログラミングなどでは重要な概念です。
11
+ staticではないフィールドにprivateを設定するとコンストラクタでしか代入できなくなります。全てがfinalなフィールのオブジェクトは**不変(immutable)**オブジェクトともいわれ、関数型プログラミングなどでは重要な概念です。(ただし、完全に不変オブジェクトであるにはフィールドの参照値が指す先のオブジェクトも不変オブジェクトでなくてはなりません)
12
12
 
13
13
 
14
14
 
15
- 不変オブジェクトは一見不便に見えますが、マルチスレッドやテストでその利便性がわかります。不変であるため、そのオブジェクトを扱うメソッドは(引数のオブジェクトに対する副作用さえ無ければ)何もしなくてもスレッドセーフになり、面倒な同期やロックを考える必要が無くなります。また、状態の変化が無いため、状態の変化に対するテストが不要になります。状態が変わることによって振る舞いが変わるようなオブジェクトのテストはかなり面倒ですが、それをまるまる省けると言うことです。
15
+ 不変オブジェクトは後から変更できないために一見不便に見えますが、マルチスレッドやテストでその利便性がわかります。不変であるため、そのオブジェクトを扱うメソッドは(引数のオブジェクトその内部で使うグローバルオブジェクトついて副作用無ければ)何もしなくてもスレッドセーフになり、面倒な同期やロックを考える必要が無くなります。また、状態の変化が無いため、状態の変化に対するテストが不要になります。状態が変わることによって振る舞いが変わるようなオブジェクトのテストはかなり面倒ですが、それをまるまる省けると言うことです。
16
16
 
17
17
 
18
18
 
@@ -22,7 +22,7 @@
22
22
 
23
23
  ```Java
24
24
 
25
- public Person changeName(Label Name) {
25
+ public Person changeName(Label name) {
26
26
 
27
27
  return new Person(name, this.address);
28
28
 
@@ -36,7 +36,19 @@
36
36
 
37
37
 
38
38
 
39
- ただ、今回のコードはLabelがメソッドを追加するだけで不変オブジェクトでは無くなるため少し片手落ちのような気
39
+ ただ、今回のコードのPerson必ずしも不変オブジェクトであると限らず例え不変オブジェクトであって、スレッドセーフと限りせん
40
+
41
+
42
+
43
+ まず、Labelが不変オブジェクトと限らないと言うことです。Labelの_labelにfinalが無いからではありません。現在の実装では_labelを生成後に変更することはできないため、その意味では不変です。また、String自体は不変オブジェクトです。しかし、Labelのサブクラスも同様に不変である問い保証はありません。PersonはLablelおよびそのサブクラスを受け付けるため、Personの不変性が崩れる可能性があります。これを完全に防ぐにはLabel自身にfinalをつけるか、Labelそのもの以外は例外で弾くかしないと無理でしょう。
44
+
45
+
46
+
47
+ 次にスレッドセーフかですが、副作用を伴うSystem.out.println()を使っているため、その条件を満たしていません。自動的にスレッドセーフと言えるのは不変オブジェクト以外を扱わず、一切の副作用がない場合です。これを自動的に検知するような仕組みはJava自体にはありません。
48
+
49
+
50
+
51
+ 最後に、上を修正してPersonを不変負ぶえ区と似しても、そのサブクラスは同じく不変オブジェクトであるは限りません。Person型とされる物は全て不変と扱ってはいけないと言うことです。これを防ぐには同じくPersonクラス自体をfinalにする必要があるでしょう。その意味では、少し片手落ちのような気もします。
40
52
 
41
53
 
42
54