回答編集履歴
5
細部の修正
answer
CHANGED
@@ -47,7 +47,7 @@
|
|
47
47
|
|
48
48
|
```java
|
49
49
|
class Test1 {
|
50
|
-
void
|
50
|
+
void method() {
|
51
51
|
B b = new B();
|
52
52
|
System.out.println(b.value.endsWith("ge"));
|
53
53
|
}
|
@@ -56,8 +56,8 @@
|
|
56
56
|
|
57
57
|
一方、Test2はコンパイルできません。
|
58
58
|
```java
|
59
|
-
class
|
59
|
+
class Test2 {
|
60
|
-
void
|
60
|
+
void method() {
|
61
61
|
A a = new B();
|
62
62
|
System.out.println(a.value.endsWith("ge"));
|
63
63
|
}
|
4
コメントで指摘を受けた点について修正
answer
CHANGED
@@ -30,8 +30,39 @@
|
|
30
30
|
}
|
31
31
|
```
|
32
32
|
|
33
|
-
さて、DogクラスはAnimalクラスより正確に犬という存在を表しています。いいかえると、DogクラスはAnimalクラスより犬に特化したクラスとなっています。これが継承の一番重要なポイントで
|
33
|
+
さて、DogクラスはAnimalクラスより正確に犬という存在を表しています。いいかえると、DogクラスはAnimalクラスより犬に特化したクラスとなっています。しかし、あるクラスを継承しているのならば、そのクラスを実際に使う側は何も考えずにそのあるクラスと全く同じ使い方ができます。この例で言うならば、「動物全体からその派生である犬に限定したとしても、動物が鳴くし歩くなら、犬も鳴くし歩く」のです。これが継承の一番重要なポイントです。これは要するに、スーパークラスの場所を任意のサブクラスで置き換えたとしても正常に動くはずであるということになります。
|
34
34
|
|
35
|
-
|
35
|
+
----
|
36
|
+
追記
|
37
|
+
javaには隠蔽という仕様があるため、必ずしもそうとは言えない場面も存在します。たとえば、次のAとB二つのクラスに対して、Test1は正しく実行できます。
|
36
38
|
|
37
|
-
|
39
|
+
```java
|
40
|
+
class A {
|
41
|
+
public int value = 5;
|
42
|
+
}
|
43
|
+
class B extends A {
|
44
|
+
public String value = "Hoge Hoge";
|
45
|
+
}
|
46
|
+
```
|
47
|
+
|
48
|
+
```java
|
49
|
+
class Test1 {
|
50
|
+
void method1() {
|
51
|
+
B b = new B();
|
52
|
+
System.out.println(b.value.endsWith("ge"));
|
53
|
+
}
|
54
|
+
}
|
55
|
+
```
|
56
|
+
|
57
|
+
一方、Test2はコンパイルできません。
|
58
|
+
```java
|
59
|
+
class Test {
|
60
|
+
void method1() {
|
61
|
+
A a = new B();
|
62
|
+
System.out.println(a.value.endsWith("ge"));
|
63
|
+
}
|
64
|
+
}
|
65
|
+
```
|
66
|
+
というのも、隠蔽の場合は実際の型(変数に格納されたオブジェクトの型)ではなく、見た目の型(変数の型)がアクセスする先に影響するからです。ここがオーバーライドとは大きく違う点です。
|
67
|
+
|
68
|
+
以上余談でした。
|
3
コードの修正
answer
CHANGED
File without changes
|
2
コードの修正
answer
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
```java
|
6
6
|
class Animal {
|
7
7
|
public String bark() {
|
8
|
-
|
8
|
+
return "動物が鳴きます";
|
9
9
|
}
|
10
10
|
|
11
11
|
public String walk() {
|
@@ -20,7 +20,7 @@
|
|
20
20
|
class Dog extends Animal {
|
21
21
|
@Override
|
22
22
|
public String bark() {
|
23
|
-
return "ワンワン";
|
23
|
+
return "犬がワンワンと鳴きます";
|
24
24
|
}
|
25
25
|
|
26
26
|
@Override
|
1
文法の修正
answer
CHANGED
@@ -34,4 +34,4 @@
|
|
34
34
|
|
35
35
|
スーパークラスはサブクラスよりも必ず汎用的なものです。逆に言うと、サブクラスの動作はすべてスーパークラスで想定された動作になっているはずです。つまり、継承するということは、ある領域により特化したクラスを作るということに他なりません。しかし、どれだけ特化したとしても、スーパークラスで定義された動作の範疇であるならば、そのクラスを実際に使う側は何も考えずにスーパークラスと全く同じ使い方ができます。先程の例で言うならば、「動物全体から犬に限定したとしても、動物が鳴くし歩くなら、犬も鳴くし歩く」のです。
|
36
36
|
|
37
|
-
これこそがオブジェクト指向の考え方の根本といっても過言ではないでしょう。__継承は、スーパークラスの挙動を変更するために行う訳ではありません__。この考えは継承に対する重大な誤解です。むしろ、継承はスーパークラスの挙動をより特化して実装し直すためにするのです。GUIのButtonくらすは黄色くないかもしれません。仮にこれを黄色くするため、YellowButtonというクラスを
|
37
|
+
これこそがオブジェクト指向の考え方の根本といっても過言ではないでしょう。__継承は、スーパークラスの挙動を変更するために行う訳ではありません__。この考えは継承に対する重大な誤解です。むしろ、継承はスーパークラスの挙動をより特化して実装し直すためにするのです。GUIのButtonくらすは黄色くないかもしれません。仮にこれを黄色くするため、Buttonを継承してYellowButtonというクラスを作ったとすると、YellowButtonクラスは「黄色」というより特化した特徴を付け加えるために作ったButtonのサブクラスと考えるべきです。
|