หลักการแทนที่ของ Rich OCP ในฐานะหลักการระดับสูงของ OO สนับสนุนการใช้ "นามธรรม" และ "polymorphism" เพื่อเปลี่ยนโครงสร้างคงที่ในการออกแบบเป็นโครงสร้างแบบไดนามิกเพื่อรักษาสิ่งที่แนบมาของการออกแบบ "บทคัดย่อ" เป็นฟังก์ชั่นที่จัดทำโดยภาษา "polymorphism" ถูกนำมาใช้โดยความหมายที่สืบทอดมา
หลักการทดแทน Richter ประกอบด้วย 4 ความหมายต่อไปนี้:
ตอนนี้เราสามารถอธิบายความหมายสี่ประการข้างต้น
คลาสย่อยสามารถใช้วิธีการนามธรรมของคลาสแม่ แต่ไม่สามารถแทนที่วิธีการที่ไม่ได้รับการรับรองของคลาสแม่
เมื่อเรากำลังออกแบบระบบเรามักจะออกแบบอินเทอร์เฟซหรือคลาสนามธรรมจากนั้นคลาสย่อยใช้วิธีการนามธรรม ใช้หลักการทดแทน Richter จริง ๆ ที่นี่ เป็นเรื่องง่ายที่จะเข้าใจว่าคลาสย่อยสามารถใช้วิธีนามธรรมของคลาสแม่ ในความเป็นจริงคลาสย่อยจะต้องใช้วิธีนามธรรมของคลาสแม่อย่างเต็มที่แม้ว่าพวกเขาจะเขียนวิธีที่ว่างเปล่ามิฉะนั้นพวกเขาจะรวบรวมและรายงานข้อผิดพลาด
จุดสำคัญของหลักการทดแทนของริกเตอร์คือมันไม่สามารถครอบคลุมวิธีการที่ไม่ได้รับการรับรองของคลาสแม่ วิธีการที่ได้รับการปรับปรุงอย่างดีในคลาสหลักคือการตั้งค่าชุดข้อมูลจำเพาะและสัญญา แม้ว่ามันจะไม่บังคับให้คลาสย่อยทั้งหมดให้สอดคล้องกับข้อกำหนดเหล่านี้หากคลาสย่อยโดยพลการแก้ไขวิธีการที่ไม่ได้รับการรับรองเหล่านี้โดยพลการมันจะทำลายระบบการสืบทอดทั้งหมด หลักการของการทดแทน Lizur เป็นการแสดงออกถึงความหมายนี้
ในแนวคิดการออกแบบเชิงวัตถุการสืบทอดคุณสมบัตินี้นำมาซึ่งความสะดวกสบายในการออกแบบระบบ แต่ก็มีความเสี่ยงบางอย่างที่มาจากมัน ตัวอย่างต่อไปนี้ใช้เพื่อแสดงให้เห็นถึงความเสี่ยงของการสืบทอด เราจำเป็นต้องทำหน้าที่ของการลบสองตัวเลขและคลาส A นั้นรับผิดชอบ
คลาส A {public int func1 (int a, int b) {return ab; }} ไคลเอนต์คลาสสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {a = new a (); System.out.println ("100-50 ="+a.func1 (100, 50)); System.out.println ("100-80 ="+A.Func1 (100, 80)); - ผลการทำงาน:
100-50 = 50100-80 = 20
ต่อมาเราจำเป็นต้องเพิ่มฟังก์ชั่นใหม่: เติมสองตัวเลขให้เสร็จสมบูรณ์แล้วสรุปด้วย 100 และคลาส B มีความรับผิดชอบ นั่นคือคลาส B ต้องทำฟังก์ชั่นสองฟังก์ชั่น:
ตัวเลขสองตัวลบ
เพิ่มสองตัวเลขจากนั้นเพิ่ม 100
เนื่องจากคลาส A ได้ใช้ฟังก์ชันแรกหลังจากคลาส B สืบทอดคลาส A คุณจะต้องทำฟังก์ชั่นที่สองให้เสร็จสมบูรณ์เท่านั้น รหัสมีดังนี้:
คลาส B ขยาย {public int func1 (int a, int b) {return a+b; } public int func2 (int a, int b) {return func1 (a, b) +100; }} ไคลเอนต์คลาสสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {b b = new b (); System.out.println ("100-50 ="+b.func1 (100, 50)); System.out.println ("100-80 ="+b.func1 (100, 80)); System.out.println ("100+20+100 ="+b.func2 (100, 20)); - หลังคลาส B เสร็จสมบูรณ์ผลการดำเนินการ:
100-50 = 150100-80 = 180100+20+100 = 220
เราพบว่าฟังก์ชั่นการลบที่เดิมทำงานตามปกติมีข้อผิดพลาด เหตุผลก็คือเมื่อคลาส B ตั้งชื่อวิธีการจะเขียนวิธีการของคลาสแม่โดยไม่ตั้งใจทำให้รหัสทั้งหมดที่ใช้ฟังก์ชันการลบเพื่อเรียกวิธีการเขียนใหม่ของคลาส B ทำให้เกิดข้อผิดพลาดในฟังก์ชันปกติดั้งเดิม ในตัวอย่างนี้หลังจากอ้างถึงฟังก์ชั่นที่เสร็จสมบูรณ์โดยฐานคลาส A และเปลี่ยนเป็น subclass B จะมีข้อยกเว้นเกิดขึ้น ในการเขียนโปรแกรมจริงเรามักจะทำฟังก์ชั่นใหม่โดยการเขียนวิธีการคลาสแม่อีกครั้ง แม้ว่าจะเป็นเรื่องง่ายที่จะเขียน แต่ความสามารถในการนำกลับมาใช้ใหม่ของระบบการสืบทอดทั้งหมดจะค่อนข้างแย่โดยเฉพาะอย่างยิ่งเมื่อมีการใช้ polymorphism บ่อยขึ้นความน่าจะเป็นของข้อผิดพลาดในการทำงานของโปรแกรมนั้นสูงมาก หากคุณต้องเขียนวิธีการคลาสแม่อีกครั้งวิธีการทั่วไปคือ: คลาสหลักและชั้นเด็กดั้งเดิมสืบทอดคลาสฐานที่เป็นที่นิยมมากขึ้นลบความสัมพันธ์การสืบทอดดั้งเดิมและใช้การพึ่งพาการรวมการรวมกันและความสัมพันธ์อื่น ๆ แทน