30

overrideディレクティブとreintroduceディレクティブの違いは何ですか? inheritedまた、オーバーライドされたメソッドでキーワードを使用してはいけないのはいつですか?

4

4 に答える 4

48

優れたところでジムの答えへの参照は、ディレクティブをいつどこで使用するかを説明しただけでした。答えの別の部分は、なぜそれらがとにかく必要なのかということです。多くの言語はそれらがなくてもうまくやっていますよね?Delphi Object Pascal言語の側面を設計するとき、OOP(オブジェクト指向プログラミング)は数年前から主流でした。この間、これらの概念を採用した多くの言語(Turbo Pascal、C ++など)を使用してアプリケーションフレームワークを開発すると、私が「バージョン2」と呼んでいた問題に悩まされることがわかりました。

言語Xを使用してすばらしいフレームワークを開発し、バージョン1としてリリースしたとします。ユーザーはそれができることをすべて絶賛し、頻繁に使用されるようになりました。成功を収めて、さらに素晴らしいバージョン2をリリースすることにしました。特に、完全な下位互換性があることを確認しました。突然、ユーザーは奇妙な行動を報告し始めました。彼ら自身の仮想メソッドは奇妙な時に呼び出されていました。多くの人が、古いコードは新しいバージョンではコンパイルされないと報告しました。変。すべて同じオブジェクト、メソッド、および機能がまだ残っています。いくつかの基本クラス、いくつかの新しいオブジェクトタイプ、およびいくつかの新しいオプション機能にいくつかの仮想メソッドを追加するだけでした。どうしたの?

オーバーライドおよび再導入ディレクティブは、仮想メソッドを実際にオーバーライドするために、仮想ディレクティブの代わりにオーバーライドディレクティブを使用する必要があることを要求することにより、この問題を排除するのに役立ちます。祖先の仮想メソッドの1つと同じ名前の独自の仮想メソッドを導入した場合、コンパイラは警告を発しますが、それでも正しいことを行います。この場合、reintroduceを使用すると、その警告が抑制されるだけでなく、意図したソースに文書化するのにも役立ちます。

オーバーライドおよび再導入ディレクティブがないと、すべてのユーザーを壊すことを恐れずにフレームワークを継続的に進化させることはできません。また、新しいバージョンがリリースされるたびにユーザーが大規模な変更を行う必要がある場合、ユーザーは新しいバージョンを採用することを嫌がります。最後に、「オーバーライド」を使用すると、フレームワーク設計者は、ユーザーコードを壊すことなく、祖先の仮想のタイプを変更することもできます。たとえば、Delphiでは、多くのメソッドが「動的」とマークされています。これは、ポリモーフィズムのテーブルベースのランタイムメソッドルックアップ形式です。通常の仮想ほど高速ではないため、通常、オーバーライドされることはめったにないメソッドや、余分なオーバーヘッドに気付かないユーザーアクションへの応答に使用されます。フレームワークのV1で、メソッドが「動的」とマークされているとします。しかし実際には、それはオーバーライドされ、意図した以上に呼び出されることになりました。V2では、ユーザーのコードが壊れることを恐れずに「仮想」に変更できます。

この問題を認識する言語は、DelphiのObjectPascal言語だけではありません。C#では、まったく同じ理由で「オーバーライド」ディレクティブを使用する必要があります。C ++標準委員会は最終的に問題を認識し、それをサポートするために言語を変更しています...ある種。C ++では、メソッドの名前とパラメーターリストが祖先の仮想と一致する場合、それはオーバーライドです(子孫で「仮想」と言わなくても!)。今後の新しいC++標準では、「仮想」を指定し、署名が一致しない場合、それは現在のクラスに導入された新しい仮想メソッドです。祖先との署名の一致があり、ライターがオーバーライドすることを意図していなかった場合、「新しい」

于 2009-04-12T17:53:03.157 に答える