web-dev-qa-db-ja.com

クラスはそのサブクラスについて知っている必要がありますか?

クラスはそのサブクラスについて知っている必要がありますか?クラスは、たとえば、特定のサブクラスに固有の何かを行う必要がありますか?

私の本能はそれが悪いデザインだと私に話します、それはある種のアンチパターンのようです。

24
m4design

クラスの概念が意味する答えは「ノー」です。

処理しているアクション、データ、またはリレーションはすべて、すべてのサブクラスの一部です。実際の型をチェックせずにスーパークラスで処理する必要があります。または、それは一部のサブクラスにのみ適用されます-次に、正しいことを行うには実行時の型チェックを実行する必要があります。スーパークラスは、他の誰かがそれから継承するたびに変更する必要があります(または黙って間違って行う可能性があります)。派生クラスを変更すると、変更されていないスーパークラスなどが壊れる可能性があります。

要するに、あなたは手に負えないそのような解決策を拒絶するのに通常十分に悪い多くの悪い結果を得る。いくつかのサブクラスが同じことを行い、コードの重複を避けたい場合(実際には常に良いことです)、より良い解決策は、それらすべてのサブクラスがコードを継承できる中間レベルのクラスを導入することです。

32
Kilian Foth

すべきだけではなく、単にできない!通常、クラスはいつでもどこでも拡張できます。作成時にexistを行わなかったクラスでも拡張できます。

一部の言語では、拡張クラスをスーパークラスで制御できます。 Scalaでは、クラスをsealedとしてマークできます。これは、同じコンパイル単位(ソースファイル)内の他のクラスによってのみ拡張できることを意味します。ただし、それらのサブクラスがalsosealedまたはfinalでない限り、サブクラスは他のクラスによってさらに拡張できます。

Scalaでは、これは閉じた代数データ型をモデル化するために使用されるため、正規のHaskell List型:

data List a = Nil | Cons a (List a)

Scalaでこのようにモデル化できます:

sealed trait List[+A]

case object Nil extends List[Nothing]

final case class Cons[+A] extends List[A]

また、Listsealedであり、ファイルの外に拡張できないため、Consfinalであり、まったく拡張できず、Nilobjectであるため、onlyこれら2つのサブ「クラス」が存在することを保証できます。とにかく拡張することはできません。

しかし、これは特定のユースケース(継承による代数的データ型のモデル化)であり、この場合でも、スーパークラスはそのサブクラスについて実際には認識していません。 ListNilの大文字と小文字を区別する場合、後ろに後ろにポップアップ表示されるother代替案がないことは、Consタイプのserに対する保証です。 。

16
Jörg W Mittag

簡単な答えは「いいえ」です。

これはコードをもろくし、オブジェクト指向プログラミングの2つの基本原則を侵害します。

  • リスコフ置換の原則
  • 開閉原理
4

はい、時々。たとえば、サブクラスの数が限られている場合などです。 訪問者パターン は、このアプローチの有用性を示しています。

例:明確に定義された文法の抽象構文ツリー(AST)ノードは、すべてのノードタイプを処理するためのビジターパターンを実装する単一のNodeクラスからすべて継承できます。

1
lorus

会社用のコンポーネントを作成し、後で退職した後、誰かが自分の目的のためにコンポーネントを拡張した場合、そのことについて知らせておく必要がありますか?

番号!

クラスと同じです。あなたの本能を信頼。

1