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

回答編集履歴

1

サブクラス->親クラス

2016/04/07 14:27

投稿

raccy
raccy

スコア21807

answer CHANGED
@@ -82,7 +82,7 @@
82
82
 
83
83
  注意すべきなのは、mixinと似たような事ができるけど、mixinではないものもあると言うことです。
84
84
 
85
- * PHPのtraitは本物のトレイトです。平坦化されるためmixinではありません。(Scalaのtraitは名前に反して、トレイトではなくmixinです。)
85
+ * PHPのtraitは本物のトレイトです。平坦化されるためmixinではありません。トレイトはmixinと違い継承関係(is-a)を持ちません。(Scalaのtraitは名前に反して、トレイトではなくmixinです。)
86
86
  * Javaでは、interfaceでdefault付きメソッドを定義することで、mixinに近い事が実現できます。しかし、interfaceは実装する(implement)ものであり、mixinではありませんし、フィールド定義ができないなどの制限があります。
87
87
  * C#では、interfaceと拡張メソッドで、mixinに近い事が実現できます。しかし、これも、mixinと似たようなことをしたいときのテクニックであり、mixinではありませんし、フィールド定義ができないなどの制限があります。
88
88
  * Pythonは多重継承ができるため、多重継承を使えばmixinと同じ事ができます。
@@ -90,7 +90,7 @@
90
90
  ###多重継承の問題点
91
91
  > ・衝突した場合実装も含めて後から読み込んだ内容で必ず上書きする、というルールを加えても駄目なのでしょうか?
92
92
 
93
- Pythonの多重継承では探索順位を決め、衝突した場合でも、大丈夫のようにしています。
93
+ 衝突時のルールを言語仕様としてきちんと決めていれば、駄目ではありません。例えば、Pythonの多重継承では探索順位を決め、衝突した場合でも、大丈夫のようにしています。(ただし、Pythonでは、後を上書きでは無く、前に定義されたものから探索になります)
94
94
 
95
95
  > ・何が問題?
96
96
  > ・多重継承する際、スーパークラスそれぞれに優先順位は付けられないのでしょうか?
@@ -161,6 +161,6 @@
161
161
  }
162
162
  ```
163
163
 
164
- 上のコードはPythonとほぼ同じ事をしているはずなのにコンパイルエラーになります。まず、`x.b()`がエラーになるのは、C++ではPythonのようにサブクラスに優先順位が無いため、B0とB1のどちらを使えばいいのかわからないからです。`x.a()`も同じです。C++では、B0経由のAとB1経由のAの二つのAが存在し、a()も二つ持つことになります。これもどちらを使えば良いのかわからないため、エラーになります。ただ、キャストして型を明示すれば一応解決できます。例えば`static_cast<B0>(x).b()`とすればいいのです。他にも、virtualを使うなどでAを一つだけにする方法があります。
164
+ 上のコードはPythonとほぼ同じ事をしているはずなのにコンパイルエラーになります。まず、`x.b()`がエラーになるのは、C++ではPythonのようにクラスに優先順位が無いため、B0とB1のどちらを使えばいいのかわからないからです。`x.a()`も同じです。C++では、B0経由のAとB1経由のAの二つのAが存在し、a()も二つ持つことになります。これもどちらを使えば良いのかわからないため、エラーになります。ただ、キャストして型を明示すれば一応解決できます。例えば`static_cast<B0>(x).b()`とすればいいのです。他にも、virtualを使うなどでAを一つだけにする方法があります。
165
165
 
166
166
  このようにC++での失敗をみた多くの人たちは多重継承を避けることにしました。Pythonのように厳密な優先順位により問題を解決した言語もありますが、Javaのように単一継承にして複雑性を避けるという言語の方法が多いようです。ただ、どちらも一長一短であり、どちらが優れているかというのはあまりないように思います。