Java におけるリヒター置換原理の概要

黄舟
リリース: 2017-08-10 09:37:51
オリジナル
1612 人が閲覧しました

この記事では主にリヒターの置換原理の関連情報を詳しく紹介します。興味のある方は参考にしてください。

リヒターの置換原理について話しましょう。

定義 1: 型 T1 のすべてのオブジェクト o1 に対して、型 T2 のオブジェクト o2 が存在する場合、T1 で定義されたすべてのプログラム P は、すべてのオブジェクト o1 が o2 に置き換えられたときに、変更はありません。動作において、タイプ T2 はタイプ T1 のサブタイプです。

定義 2: 基本クラスを参照するすべての場所は、そのサブクラスのオブジェクトを透過的に使用できなければなりません。

問題の原因: クラス A によって完了される関数 P1 があります。ここで関数 P1 を拡張する必要があります。拡張された関数は P です。ここで、P は元の関数 P1 と新しい関数 P2 で構成されます。新しい機能 P は、カテゴリ A のサブカテゴリ B によって実装されます。サブカテゴリ B は、新しい機能 P2 を完成させる間に、元の機能 P1 が誤動作する可能性があります。

解決策: 継承を使用する場合は、Liskov 置換原則に従います。クラス B がクラス A を継承する場合、新しい関数 P2 を完成させるために新しいメソッドを追加する場合を除き、親クラス A のメソッドをオーバーライドしたり、親クラス A のメソッドをオーバーロードしたりしないようにしてください。 interned次の意味とともに、親クラスで実装されたすべての方法(抽象的な方法とは対照的に)は、これらのサブクラスに必須ではありませんが、実際に一連の仕様と契約を設定していますただし、サブクラスがこれらの非抽象メソッドを任意に変更すると、継承システム全体に損傷を与えることになります。リスコフの置換原理はこの意味を表しています。

— オブジェクト指向プログラミングの 3 つの主要な機能の 1 つである継承は、プログラミングに大きな利便性をもたらしますが、デメリットももたらします。たとえば、継承を使用すると、プログラムに侵入が生じ、プログラムの移植性が低下し、クラスが他のクラスに継承されている場合、このクラスを変更する必要がある場合、すべてのサブクラスを考慮する必要があります。 .クラスであり、親クラスが変更されると、サブクラスに関係するすべての関数が誤動作する可能性があります。

継承のリスクの例を挙げると、クラス A で処理される 2 つの数値を減算する関数を完了する必要があります。


class A{ 
 public int func1(int a, int b){ 
  return a-b; 
 } 
} 

public class Client{ 
 public static void main(String[] args){ 
  A a = new A(); 
  System.out.println("100-50="+a.func1(100, 50)); 
  System.out.println("100-80="+a.func1(100, 80)); 
 } 
}
ログイン後にコピー

実行結果:


100-50=50

100-80=20



その後、新しい関数を追加する必要があります: 2 つの数値の加算を完了してから、それを追加します。から100まで、クラスBが担当します。つまり、クラス B は、


2 つの数値を減算する 2 つの関数を完了する必要があります。

2 つの数字を足し、100 を足します。
クラス A は既に最初の関数を実装しているため、クラス B がクラス A を継承した後は、2 番目の関数を完了するだけで済みます。コードは次のとおりです。実行結果:


100-50=150

100-80=180

100+20+100=220


本来正常に動作していた減算関数でエラーが発生していることが分かりました。その理由は、クラス B がメソッドに名前を付けるときに親クラスのメソッドを誤って書き換えたため、減算関数を実行するすべてのコードがクラス B の書き換えられたメソッドを呼び出すことになり、本来は正常に実行されていた関数でエラーが発生するためです。この例では、基本クラス A で完成した関数を参照し、サブクラス B に置き換えた後、例外が発生しました。実際のプログラミングでは、親クラスのメソッドを書き換えることで新しい関数を完成させることが多いですが、記述は簡単ですが、継承系全体の再利用性が相対的に悪くなり、特に多態性を多用した場合にはプログラムエラーが発生する可能性が高くなります。すごく高い。親クラスのメソッドを書き直す必要がある場合、より一般的なアプローチは、元の親クラスとサブクラスの両方がより一般的な基本クラスを継承し、元の継承関係を削除し、代わりに依存関係、集約、組み合わせ、およびその他の関係を使用することです。置換原則の原理に関して、Syli は次のようになります。 サブクラスは親クラスの機能を拡張できますが、親クラスの元の機能を変更することはできません。

これには次の 4 つの意味レベルが含まれます:




サブクラスは親クラスの抽象メソッドを実装できますが、親クラスの非抽象メソッドをオーバーライドすることはできません。


独自の一意のメソッドをサブクラスに追加できます。

サブクラスのメソッドが親クラスのメソッドをオーバーライドする場合、メソッドの前提条件 (つまり、メソッドの仮パラメータ) は、親クラスのメソッドの入力パラメータよりも緩くなります。

  • サブクラスのメソッドが親クラスの抽象メソッドを実装する場合、メソッドの事後条件 (メソッドの戻り値) は親クラスの事後条件よりも厳しくなります。

  • 信じられないことのように思えます。なぜなら、私たち自身のプログラミングではリスコフ置換原則に違反することがよくあることがわかりますが、それでもプログラムは正常に実行されます。それで、誰もがこの疑問を抱くでしょう、もし私がリスコフ置換原則に従わないと主張したら、結果はどうなるでしょうか?

  • その結果:

    作成したコードで問題が発生する可能性が大幅に増加します。

以上がJava におけるリヒター置換原理の概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート