คำถามติดแท็ก liskov-substitution

สำหรับคำถามเกี่ยวกับหลักการแทนที่ Liskov ในการออกแบบเชิงวัตถุ

10
นี่เป็นการละเมิดหลักการทดแทน Liskov หรือไม่?
สมมติว่าเรามีรายการของเอนทิตีงานและProjectTaskประเภทย่อย สามารถปิดงานได้ตลอดเวลายกเว้นงานProjectTasksที่ไม่สามารถปิดได้เมื่อพวกเขามีสถานะเป็นเริ่มต้น UI ควรตรวจสอบให้แน่ใจว่าไม่มีตัวเลือกในการปิดการเริ่มต้นทำงานProjectTaskแต่มีการป้องกันบางอย่างในโดเมน: public class Task { public Status Status { get; set; } public virtual void Close() { Status = Status.Closed; } } public class ProjectTask : Task { public override void Close() { if (Status == Status.Started) throw new Exception("Cannot close a started Project Task"); base.Close(); } …

8
LSP เทียบกับการทดแทน OCP / Liskov VS เปิดปิด
ฉันพยายามที่จะเข้าใจหลักการของ OOP และฉันได้ข้อสรุปว่า LSP และ OCP มีความคล้ายคลึงกัน (ถ้าไม่พูดมากกว่านี้) หลักการเปิด / ปิดระบุ "เอนทิตีของซอฟต์แวร์ (คลาส, โมดูล, ฟังก์ชั่น, อื่น ๆ ) ควรจะเปิดสำหรับการขยาย แต่ปิดสำหรับการปรับเปลี่ยน" ในคำง่ายๆ LSP ระบุว่าอินสแตนซ์ใด ๆ ของFooสามารถถูกแทนที่ด้วยอินสแตนซ์ใด ๆBarที่ได้มาจากFooและโปรแกรมจะทำงานในลักษณะเดียวกัน ฉันไม่ใช่โปรแกรมเมอร์ OOP มืออาชีพ แต่สำหรับฉันแล้วดูเหมือนว่า LSP จะเป็นไปได้ก็ต่อเมื่อBarได้รับมาจากFooไม่ได้เปลี่ยนแปลงอะไรเลย แต่จะขยายออกไปเท่านั้น นั่นหมายความว่าโดยเฉพาะอย่างยิ่งโปรแกรม LSP จะเป็นจริงเฉพาะเมื่อ OCP เป็นจริงและ OCP เป็นจริงเฉพาะในกรณีที่ LSP เป็นจริง นั่นหมายความว่าพวกเขาเท่าเทียมกัน ช่วยแก้ให้ด้วยนะถ้าฉันผิด. ฉันต้องการเข้าใจแนวคิดเหล่านี้จริงๆ ขอบคุณมากสำหรับคำตอบ

3
ความแตกต่างระหว่างคลาสย่อยและประเภทย่อยคืออะไร?
คำตอบการจัดอันดับสูงสุดที่จะคำถามนี้เกี่ยวกับ Liskov ชดเชยหลักการใช้เวลาปวดจะแยกแยะระหว่างข้อกำหนดย่อยและsubclass นอกจากนี้ยังทำให้จุดที่บางภาษาทำให้ทั้งสองเป็นคู่ในขณะที่คนอื่นทำไม่ได้ สำหรับภาษาเชิงวัตถุที่ฉันคุ้นเคยมากที่สุด (Python, C ++), "type" และ "class" เป็นแนวคิดที่มีความหมายเหมือนกัน ในแง่ของ C ++ การแยกประเภทย่อยและคลาสย่อยหมายความว่าอย่างไร กล่าวว่าเช่นว่าFooเป็น subclass FooBaseแต่ไม่ได้เป็นชนิดย่อยของ หากfooเป็นตัวอย่างของFooสายนี้จะ: FooBase* fbPoint = &foo; ไม่ถูกต้องอีกต่อไป?

14
มีรูปแบบภาษาหรือการออกแบบที่อนุญาต * การกำจัด * ของพฤติกรรมวัตถุหรือคุณสมบัติในลำดับชั้นของคลาสหรือไม่?
ข้อบกพร่องที่รู้จักกันดีของลำดับชั้นของคลาสดั้งเดิมคือมันไม่ดีเมื่อพูดถึงการสร้างแบบจำลองโลกแห่งความจริง ตัวอย่างเช่นพยายามเป็นตัวแทนสายพันธุ์สัตว์ด้วยชั้นเรียน จริงๆแล้วมีปัญหาหลายอย่างเมื่อทำเช่นนั้น แต่สิ่งหนึ่งที่ฉันไม่เคยเห็นวิธีแก้คือเมื่อ "พฤติกรรม" หรือคุณสมบัติย่อยที่สูญเสียไปซึ่งถูกกำหนดไว้ในระดับซุปเปอร์คลาสเหมือนเพนกวินที่ไม่สามารถบินได้ อาจเป็นตัวอย่างที่ดีกว่า แต่นั่นเป็นสิ่งแรกที่อยู่ในใจของฉัน) ในอีกด้านหนึ่งคุณไม่ต้องการกำหนดสำหรับทุกคุณสมบัติและพฤติกรรมบางธงที่ระบุว่าเป็นปัจจุบันและตรวจสอบทุกครั้งก่อนที่จะเข้าถึงพฤติกรรมหรือทรัพย์สินนั้น คุณแค่อยากจะบอกว่านกสามารถบินได้ง่ายและชัดเจนในชั้นเรียนนก แต่มันจะดีถ้าใครสามารถนิยาม "ข้อยกเว้น" หลังจากนั้นโดยไม่ต้องใช้แฮ็คที่น่ากลัวทุกที่ สิ่งนี้มักจะเกิดขึ้นเมื่อระบบมีประสิทธิผลในขณะที่ คุณจะพบข้อยกเว้น "" ที่ไม่พอดีกับการออกแบบดั้งเดิมเลยและคุณไม่ต้องการเปลี่ยนรหัสส่วนใหญ่เพื่อรองรับมัน ดังนั้นมีบางภาษาหรือรูปแบบการออกแบบที่สามารถจัดการปัญหานี้ได้อย่างหมดจดโดยไม่ต้องมีการเปลี่ยนแปลงที่สำคัญกับ "super-class" และรหัสทั้งหมดที่ใช้หรือไม่ แม้ว่าโซลูชันจะจัดการกับเคสเฉพาะเท่านั้นโซลูชันจำนวนมากอาจรวมกันเป็นกลยุทธ์ที่สมบูรณ์ หลังจากคิดเพิ่มขึ้นฉันรู้ว่าฉันลืมเกี่ยวกับหลักการทดแทน Liskov นั่นคือเหตุผลที่คุณไม่สามารถทำได้ สมมติว่าคุณกำหนด "คุณสมบัติ / อินเทอร์เฟซ" สำหรับ "กลุ่มคุณลักษณะ" หลักทั้งหมดคุณสามารถใช้คุณลักษณะในสาขาต่าง ๆ ของลำดับชั้นได้อย่างอิสระเช่นเดียวกับลักษณะการบินที่สามารถนำไปใช้กับนกและกระรอกและปลาชนิดพิเศษบางอย่าง ดังนั้นคำถามของฉันอาจมีค่าเป็น "ฉันจะยกเลิกการใช้คุณลักษณะได้อย่างไร" หากซุปเปอร์คลาสของคุณเป็น Java Serializable คุณก็ต้องเป็นหนึ่งด้วยแม้ว่าคุณจะไม่มีวิธีในการทำให้เป็นอันดับสถานะของคุณเช่นถ้าคุณมี "Socket" วิธีหนึ่งในการทำคือการกำหนดคุณสมบัติทั้งหมดของคุณเป็นคู่ตั้งแต่เริ่มต้น: การบินและการไม่พูดถึง (ซึ่งจะโยน UnsupportedOperationException หากไม่ได้ตรวจสอบกับ) ไม่ใช่คุณสมบัติจะไม่กำหนดอินเทอร์เฟซใหม่ใด ๆ และสามารถตรวจสอบได้ง่ายๆ ดูเหมือนโซลูชันที่ "ถูก" …

9
จะมีอะไรผิดพลาดได้หากหลักการชดเชย Liskov ถูกละเมิด?
ฉันได้ติดตามคำถามที่ได้รับการโหวตอย่างสูงเกี่ยวกับการละเมิดหลักการทดแทน Liskov ฉันรู้ว่าหลักการชดเชย Liskov คืออะไร แต่สิ่งที่ยังไม่ชัดเจนในใจของฉันคือสิ่งที่อาจผิดพลาดได้หากฉันในฐานะนักพัฒนาไม่ได้คิดถึงหลักการในขณะที่เขียนโค้ดเชิงวัตถุ

5
กรณีพิเศษที่มีทางเลือกล้มเหลวละเมิดหลักการทดแทน Liskov หรือไม่?
สมมติว่าฉันมีอินเทอร์เฟซFooInterfaceที่มีลายเซ็นต่อไปนี้: interface FooInterface { public function doSomething(SomethingInterface something); } และคลาสรูปธรรมConcreteFooที่ใช้ส่วนต่อประสานนั้น: class ConcreteFoo implements FooInterface { public function doSomething(SomethingInterface something) { } } ฉันต้องการConcreteFoo::doSomething()ทำสิ่งที่ไม่ซ้ำกันหากผ่านSomethingInterfaceวัตถุชนิดพิเศษ(สมมติว่ามันถูกเรียกว่าSpecialSomething) มันเป็นการละเมิด LSP อย่างแน่นอนถ้าฉันเพิ่มเงื่อนไขของวิธีการหรือสร้างข้อยกเว้นใหม่ แต่มันจะเป็นการละเมิด LSP หรือไม่ถ้าฉันใส่SpecialSomethingวัตถุพิเศษในขณะที่ให้ทางเลือกสำหรับSomethingInterfaceวัตถุทั่วไป? สิ่งที่ต้องการ: class ConcreteFoo implements FooInterface { public function doSomething(SomethingInterface something) { if (something instanceof SpecialSomething) { // Do SpecialSomething magic } …

3
การเสริมความแข็งแกร่งของปัจจัยพื้นฐานและความอ่อนแอของ postconditions จะละเมิดหลักการทดแทน Liskov อย่างไร
ฉันอ่านว่าหลักการทดแทนของ Liskovถูกละเมิดหาก: เงื่อนไขเบื้องต้นมีความเข้มแข็งหรือ Postconditions จะอ่อนแอลง แต่ฉันยังไม่เข้าใจว่าจุดสองจุดนี้จะละเมิดหลักการเปลี่ยนตัว Liskov อย่างไร บางคนได้โปรดอธิบายด้วยตัวอย่าง โดยเฉพาะอย่างยิ่งหนึ่งในเงื่อนไขข้างต้นจะทำให้สถานการณ์ที่วัตถุ subclass ไม่สามารถทดแทนสำหรับวัตถุ superclass ได้อย่างไร

3
มีชื่อเฉพาะสำหรับบุคคลที่ผิดธรรมดา“ Square ที่สืบทอดมาจาก Rectangle” หรือไม่?
ความล้มเหลวบางอย่างของ OOP แสดงขึ้นพร้อมกับคลาส Square ที่สืบทอดมาจาก Rectangle โดยที่ Logical Square เป็นความเชี่ยวชาญเฉพาะของ Rectangle และควรสืบทอดมาจากมัน แต่ทุกอย่างจะแยกจากกันเมื่อคุณพยายามเปลี่ยนความยาวหรือความกว้างของ Square มีคำเฉพาะสำหรับการอธิบายสิ่งที่เกิดขึ้นกับกรณีนี้หรือไม่?

3
รูปแบบของรัฐละเมิดหลักการทดแทน Liskov หรือไม่?
ภาพนี้นำมาจากการใช้การออกแบบและรูปแบบที่ใช้โดเมนขับเคลื่อน: พร้อมตัวอย่างใน C # และ. NET นี่คือแผนภาพคลาสสำหรับรูปแบบสถานะที่ a SalesOrderสามารถมีสถานะต่างกันในช่วงเวลาของชีวิต อนุญาตให้ช่วงการเปลี่ยนภาพบางอย่างระหว่างรัฐที่แตกต่างกัน ตอนนี้OrderStateคลาสเป็นabstractคลาสและวิธีการทั้งหมดได้รับการสืบทอดไปยังคลาสย่อย หากเราพิจารณาคลาสย่อยCancelledซึ่งเป็นสถานะสุดท้ายที่ไม่อนุญาตให้มีการเปลี่ยนสถานะเป็นสถานะอื่นเราจะต้องoverrideใช้วิธีการทั้งหมดในคลาสนี้เพื่อโยนข้อยกเว้น ตอนนี้ไม่ได้เป็นการละเมิดหลักการทดแทนของ Liskov เนื่องจาก sublcass ไม่ควรเปลี่ยนพฤติกรรมของผู้ปกครองหรือไม่ การเปลี่ยนคลาสนามธรรมเป็นอินเตอร์เฟสแก้ไขสิ่งนี้หรือไม่? จะแก้ไขได้อย่างไร?

1
หลักการชดเชย Liskov ใช้กับคลาสที่ใช้อินเตอร์เฟสได้หรือไม่?
LSP ระบุว่าเรียนควรจะทดแทนสำหรับการเรียนฐานของพวกเขาหมายความว่าได้มาและฐานเรียนควรจะมีความหมายเทียบเท่า แต่ไม่ LSP ยังนำไปใช้กับการเรียนการใช้อินเตอร์เฟซ? กล่าวอีกนัยหนึ่งถ้าวิธีการอินเทอร์เฟซที่ใช้งานโดยคลาสนั้นมีความแตกต่างทางความหมายจากสิ่งที่ผู้ใช้คาดหวังว่าจะเป็นสิ่งนี้จะถือว่าเป็นการละเมิด LSP หรือไม่?

2
โลกแห่งความจริง - หลักการทดแทน Liskov
พื้นหลัง: ฉันกำลังพัฒนากรอบการส่งข้อความ กรอบนี้จะช่วยให้: การส่งข้อความผ่านบัสบริการ สมัครสมาชิกคิวบนบัสข้อความ สมัครสมาชิกหัวข้อบนบัสข้อความ ขณะนี้เรากำลังใช้ RabbitMQ แต่ฉันรู้ว่าเราจะย้ายไปที่ Microsoft Service Bus (บนสถานที่ตั้ง) ในอนาคตอันใกล้นี้ ฉันวางแผนที่จะสร้างชุดของอินเทอร์เฟซและการใช้งานเพื่อที่ว่าเมื่อเราย้ายไปที่ ServiceBus ฉันก็ต้องจัดเตรียมการใช้งานใหม่โดยไม่ต้องแก้ไขรหัสลูกค้าใด ๆ (เช่นผู้เผยแพร่หรือสมาชิก) ปัญหาที่นี่คือ RabbitMQ และ ServiceBus ไม่สามารถแปลได้โดยตรง ตัวอย่างเช่น RabbitMQ ขึ้นอยู่กับการแลกเปลี่ยนและชื่อหัวข้อในขณะที่ ServiceBus เป็นข้อมูลเกี่ยวกับ Namespaces และ Queues นอกจากนี้ไม่มีอินเทอร์เฟซทั่วไประหว่างไคลเอนต์ ServiceBus และไคลเอนต์ RabbitMQ (เช่นทั้งสองอาจมีการเชื่อมต่อ ICon แต่อินเทอร์เฟซแตกต่างกัน - ไม่ใช่จากเนมสเปซทั่วไป) ดังนั้นถึงจุดของฉันฉันสามารถสร้างอินเตอร์เฟซดังต่อไปนี้: public interface IMessageReceiver{ void AddSubscription(ISubscription subscriptionDetails) } เนื่องจากคุณสมบัติที่ไม่สามารถแปลได้ของทั้งสองเทคโนโลยีการปรับใช้ …

6
การเปลี่ยนแปลงในการปฏิบัติงานละเมิดหลักการการทดแทน Liskov หรือไม่?
พูดว่าฉันมี: interface Thing { GetThing(); } class FastThing : Thing { public int GetThing() { return 1; } } class SlowThing : Thing { public int GetThing() { return GetThingFromDatabase(); } } นี่เป็นการละเมิดหลักการทดแทน Liskov หรือไม่?

1
วิธีการตรวจสอบหลักการทดแทน Liskov ในลำดับชั้นการสืบทอด?
แรงบันดาลใจจากคำตอบนี้ : หลักการทดแทน Liskov ต้องการ สิ่งนั้น เงื่อนไขเบื้องต้นไม่สามารถเสริมความแข็งแกร่งในประเภทย่อย Postconditions ไม่สามารถลดลงในประเภทย่อย ค่าคงที่ของซูเปอร์ไทป์จะต้องเก็บรักษาไว้ในประเภทย่อย ข้อ จำกัด ประวัติ ("กฎประวัติศาสตร์") วัตถุนั้นได้รับการยกย่องว่าสามารถปรับเปลี่ยนได้ด้วยวิธีการของพวกเขาเท่านั้น (encapsulation) เนื่องจากชนิดย่อยอาจแนะนำวิธีการที่ไม่ปรากฏใน supertype การแนะนำวิธีการเหล่านี้อาจอนุญาตให้มีการเปลี่ยนแปลงสถานะในชนิดย่อยที่ไม่อนุญาตใน supertype ข้อ จำกัด ประวัติห้ามสิ่งนี้ ฉันหวังว่าถ้ามีคนจะโพสต์ลำดับชั้นของชั้นเรียนที่ละเมิด 4 คะแนนและจะแก้ไขได้อย่างไร ฉันกำลังมองหาคำอธิบายอย่างละเอียดเพื่อจุดประสงค์ด้านการศึกษาเกี่ยวกับวิธีระบุแต่ละจุดในลำดับชั้นและวิธีที่ดีที่สุดในการแก้ไข หมายเหตุ: ฉันหวังว่าจะโพสต์ตัวอย่างโค้ดเพื่อให้คนทำงาน แต่คำถามนั้นเกี่ยวกับวิธีระบุลำดับชั้นผิดพลาด :)

2
สแต็กขยาย LinkedList การละเมิดหลักการทดแทน Liskov หรือไม่?
คลาส LinkedList มีอยู่พร้อมกับฟังก์ชั่นเช่น add_first (), add_last (), add_after (), remove_first (), remove_last () และ remove () ขณะนี้มีคลาสสแต็กที่จัดเตรียมฟังก์ชันการใช้งานเช่น push (), pop (), peek () หรือ top () และเพื่อใช้เมธอดเหล่านี้จะขยายเมธอดคลาส LinkedList นี่เป็นการละเมิดหลักการทดแทนของ Liskov หรือไม่? ตัวอย่างเช่นพิจารณา case add_after () เพื่อเพิ่มโหนดที่ตำแหน่งที่ n ของรายการที่เชื่อมโยง สามารถทำได้ในคลาสพื้นฐาน แต่ไม่สามารถอยู่ในคลาสสแต็กได้ postconditions ถูกทำให้อ่อนลงที่นี่หรือคุณปรับเปลี่ยนวิธี add_after () เพื่อเพิ่มไปยังด้านบนสุดของสแต็กหรือไม่ นอกจากนี้หากไม่เป็นการละเมิดการออกแบบที่ไม่ดีนี้เป็นอย่างไร และคุณจะใช้ฟังก์ชั่น Stack โดยใช้คลาส LinkedList …

6
ปัญหาวงกลมวงรีสามารถแก้ไขได้โดยการย้อนกลับความสัมพันธ์หรือไม่?
การCircleยืดเวลาEllipseแบ่งหลักการ Liskov Substitionเนื่องจากมันจะแก้ไข postcondition: คุณสามารถตั้งค่า X และ Y อย่างอิสระเพื่อวาดวงรี แต่ X ต้องเท่ากับ Y เสมอสำหรับวงกลม แต่นี่ไม่ใช่ปัญหาที่เกิดจากการมี Circle เป็นชนิดย่อยของ Ellipse หรือไม่? เราไม่สามารถย้อนกลับความสัมพันธ์หรือไม่ ดังนั้นวงกลม supertype - setRadiusมันมีวิธีเดียว จากนั้นขยายวงรีวงกลมโดยการเพิ่มและsetX setYการเรียกsetRadiusใช้ Ellipse จะเป็นการตั้งค่าทั้ง X และ Y หมายถึง postcondition บน setRadius ได้รับการดูแล แต่ตอนนี้คุณสามารถตั้งค่า X และ Y ได้อย่างอิสระผ่านอินเทอร์เฟซเสริม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.