ทำไมการสืบทอดการห่อหุ้มและ polymorphism จึงไม่ใช่เสาหลักของ OOP [ปิด]


16

อยู่มาวันหนึ่งฉันไปที่แชทสแต็คล้นล้นและเห็นวลีที่ระบุว่ามรดก incapsulation และ polymorphism เป็นเสาหลักของ OOP (ในแง่ที่ว่าพวกเขาเป็นพื้นฐานการก่อสร้างเพียงอย่างเดียว)

นอกจากนี้ยังมีคำถามที่คล้ายกันที่ฉันถูกถามบ่อยมากในการสอบวิทยาลัยและการสัมภาษณ์งานและคำตอบที่ถูกต้องเสมอคือข้อความที่ออกเสียงในชื่อของคำถาม ("ใช่มรดกการห่อหุ้มและ polymorphism เป็นเสาหลักของ OOP )

แต่ในการแชทล้นมากเกินไปฉันถูกเยาะเย้ยอย่างรุนแรงผู้เข้าร่วมไม่เห็นด้วยอย่างยิ่งกับคำแถลงดังกล่าว ดังนั้นมีอะไรผิดปกติกับคำสั่งนี้

โปรแกรมเมอร์ดูเหมือนจะได้รับการฝึกฝนในสิ่งต่าง ๆ ในวิทยาลัยหลังโซเวียตและสหรัฐอเมริกาหรือไม่?

การสืบทอดการห่อหุ้มและ polymorphism ไม่ถือเป็นเสาหลักของ OOP โดยโปรแกรมเมอร์ของสหรัฐฯ / อังกฤษหรือไม่?


7
คำถามของคุณไม่มีบริบท เราไม่รู้ว่าคนในแชทกำลังคิดอะไรอยู่หรือสิ่งที่พวกเขาตอบสนอง บางทีคุณสามารถเชื่อมโยงการสนทนาในห้องสนทนาเพื่อให้เราดูได้หรือไม่ ที่กล่าวว่าฉันคิดว่านี่เป็นทางออกที่ดีที่สุดในห้องแชทมากกว่าที่นี่
Robert Harvey

1
@ Robert หลายครั้งที่ผ่านมามากเกินไป ฉันสงสัยว่าฉันจะพบลิงก์ไปยังการสนทนาได้หรือไม่ แต่ฉันยอมรับว่าบริบทเป็นสิ่งสำคัญ จะไม่โทษใครบางคนหรือแสดงตัวเองในฐานะเหยื่อผู้บริสุทธิ์ของการก้าวร้าวการแชทฉันแค่อยากรู้ความจริง
PaulD

5
เลานจ์. คุณใส่ชุดกันไฟของคุณก่อน?
Robert Harvey

1
ความหมายเดียวที่ฉันสามารถมอบให้กับประโยคได้คือ "คุณสามารถมี OOP ได้โดยไม่มีพวกเขา" (จริง แต่อย่างน้อยก็ไม่มีเหตุผลสำหรับ encapsulation) หรือ "คุณสามารถใช้มันนอก OOP ได้" หรืออะไรทำนองนั้น
SJuan76

2
Imo OO มีเสาเดียวเท่านั้นและนั่นคือ: "รัฐ" เมื่อสมองของคุณคิดว่าอยู่ในสถานะที่คุณได้รับ OO
Pieter B

คำตอบ:


40

การสืบทอดการห่อหุ้มและความหลากหลายไม่ถือเป็นเสาหลักของ OOP โดยโปรแกรมเมอร์ของสหรัฐฯ / อังกฤษหรือไม่?

พวกเขาถือว่าเป็นเสาหลักโดยโปรแกรมเมอร์จำนวนมากและวิทยาลัยหลายแห่งสอน OO ด้วยวิธีนี้

น่าเสียดายที่มันเป็นมุมมองที่สั้น

  • การสืบทอดเป็นเพียงกลไกหนึ่งที่ใช้ในการใช้งาน OOP และสามารถใช้งานแบบ OOP ได้
  • Encapsulation เป็นแนวคิดที่มีประโยชน์สำหรับการเขียนโปรแกรมทุกประเภท OOP และไม่
  • ความแตกต่างคือ ... ลักษณะ (?) เพื่ออธิบายวิธีการคำนวณพฤติกรรม มีหลายวิธีในการบรรลุถึงความหลากหลายซึ่งไม่ใช่ทั้งหมดของ OO

OOP มีพื้นฐานที่น้อยมากเนื่องจากในความเป็นจริงมันมีแนวคิดมาก: "เข้าใกล้การออกแบบโปรแกรมของคุณโดยการคิดถึงสิ่งต่าง ๆ ในฐานะวัตถุ - รวมข้อมูลและฟังก์ชันการทำงานเข้าด้วยกัน"

และในขณะที่การออกแบบโปรแกรมที่ทันสมัยใช้มุมมองที่ไม่ดีในการทำสิ่งต่าง ๆ ในแบบ "OO ล้วนๆ" โปรแกรมเมอร์ที่มีทักษะส่วนใหญ่จะยอมรับว่าหลักการ SOLID (หรือบางส่วน) เป็นผู้สมัครที่ดีกว่าสำหรับ "เสาหลักของโปรแกรมเชิงวัตถุ ใช้กับ non-OOP ได้ดี) สิ่งเหล่านี้ใช้ไม่ได้กับข้อกำหนดเหล่านี้เลย แต่พวกเขาใช้แนวคิดของเอนทิตีซอฟต์แวร์ (ซึ่งวัตถุเป็นหนึ่ง), อินเทอร์เฟซ (ซึ่งเป็น C # / Java / ฯลฯinterfaceเป็นหนึ่ง), นามธรรมและย่อยพิมพ์ (ซึ่งเป็นมรดกเป็นรูปแบบเดียว)


10
คำตอบที่เหมาะสมสำหรับคำถามที่ไม่สามารถตอบได้เป็นหลัก
Robert Harvey

3
มี OOP หรือไม่
Tulains Córdova

5
ฉันจะยืนยันว่า encapsulation เท่านั้นเป็น "เสา" ของ OOP ความแตกต่างที่ใหญ่ที่สุดระหว่าง OOP และการเขียนโปรแกรมโครงสร้างคือความคิดที่ว่าวัตถุมีรหัสและข้อมูลไม่ใช่แค่ข้อมูล (เช่นโครงสร้าง C แบบคลาสสิก) อีกสองแนวคิดที่ใช้เป็นหลักในภาษา OO แต่ไม่ จำกัด OO หรือตามที่กำหนด

3
@Snowman Encapsulation ไม่ได้ จำกัด อยู่ที่ OOP เท่านั้น ผู้คนใช้ข้อมูลนามธรรมในภาษา C และภาษาที่ใช้งานได้ตลอดเวลา
Doval

2
และ @ JörgWMittagมีคำตอบที่ดีเกี่ยวกับการส่งข้อความ แนวคิดของการส่งข้อความจำเป็นต้องมีการห่อหุ้ม โดยทั่วไปข้อความจะถูกส่งไปยังฟังก์ชันหรือวิธีการบนวัตถุซึ่งจะทำหน้าที่ในสถานะที่ถูกห่อหุ้มอยู่ ไม่ได้หมายความว่าภาษาที่ไม่ใช่ OO จะไม่สามารถส่งผ่านข้อความหรือใส่ในแค็ปซูลได้เช่นกัน แต่สิ่งเหล่านี้เป็นแนวคิดพื้นฐานของ OOP

23

tl; dr: คุณสามารถมีการสืบทอดโดยไม่มี OO คุณสามารถมี encapsulation โดยไม่มี OO คุณสามารถมี polymorphism ที่ไม่มี OO คุณสามารถมีทั้งสามอย่างในเวลาเดียวกันโดยไม่มี OO บน flipside คุณสามารถมี OO ได้โดยไม่มีการสืบทอด นอกจากนี้ยังมีการห่อหุ้มหลายประเภท (ADT-oriented และ OO) IOW encapsulation ทั้งหมดไม่ใช่ OO

รุ่นยาว:

คำว่า "การเขียนโปรแกรมเชิงวัตถุ" ถูกคิดค้นโดย Alan Kay ดังนั้นเขาจึงตัดสินใจได้ว่ามันหมายถึงอะไร และเขากำหนดวิธีนี้ :

OOP สำหรับฉันหมายถึงเพียงการส่งข้อความการเก็บรักษาในท้องถิ่นและการป้องกันและการซ่อนกระบวนการของรัฐและการผูกมัดปลายสุดของทุกสิ่ง

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

ในภายหลังเขาชี้แจงว่า " ความคิดใหญ่คือ 'การส่งข้อความ' " และรู้สึกเสียใจที่เรียกมันว่า "เชิงวัตถุ" แทนที่จะเป็น "ข้อความเชิง" เพราะคำว่า "เชิงวัตถุ" ทำให้ความสำคัญกับสิ่งที่ไม่สำคัญ (วัตถุ ) และเบี่ยงเบนความสนใจจากสิ่งที่สำคัญจริงๆ (การส่งข้อความ):

เพียงเตือนความทรงจำเบา ๆ ว่าฉันเอาความเจ็บปวดที่ OOPSLA สุดท้ายเพื่อพยายามเตือนทุกคนว่า Smalltalk ไม่เพียง แต่ไม่ได้เป็นไวยากรณ์หรือไลบรารีของชั้นเรียนเท่านั้น ฉันขอโทษที่ฉันนานมาแล้วประกาศเกียรติคุณคำว่า "วัตถุ" สำหรับหัวข้อนี้เพราะมันทำให้คนจำนวนมากมุ่งเน้นไปที่ความคิดที่น้อยกว่า

แนวคิดหลักคือ "การส่งข้อความ" - นั่นคือสิ่งที่ kernal ของ Smalltalk / Squeak เป็นเรื่องเกี่ยวกับ (และเป็นสิ่งที่ไม่เคยเสร็จสมบูรณ์ในช่วง Xerox PARC ของเรา) ภาษาญี่ปุ่นมีคำขนาดเล็ก - มา - สำหรับ "สิ่งที่อยู่ระหว่าง" - อาจเทียบเท่าภาษาอังกฤษที่ใกล้ที่สุดคือ "คั่นระหว่างหน้า" กุญแจสำคัญในการทำให้ระบบที่ยอดเยี่ยมและเติบโตได้นั้นมีมากขึ้นในการออกแบบว่าโมดูลสื่อสารได้อย่างไรมากกว่าคุณสมบัติและพฤติกรรมภายในของมัน คิดถึงอินเทอร์เน็ต - เพื่อการมีชีวิตอยู่ (ก) ต้องอนุญาตความคิดและการรับรู้ที่แตกต่างหลากหลายซึ่งอยู่นอกเหนือมาตรฐานเดียวและ (b) เพื่อให้การทำงานร่วมกันอย่างปลอดภัยระหว่างความคิดเหล่านี้มีระดับแตกต่างกัน

(แน่นอนวันนี้ผู้คนส่วนใหญ่ไม่ได้สนใจวัตถุ แต่เรียนซึ่งผิดยิ่งกว่า)

การส่งข้อความเป็นพื้นฐานของ OO ทั้งในฐานะคำอุปมาและเป็นกลไก

หากคุณส่งข้อความถึงใครบางคนคุณไม่รู้ว่าพวกเขาทำอะไรกับมัน เพียงสิ่งที่คุณสามารถสังเกตคือการตอบสนองของพวกเขา คุณไม่ทราบว่าพวกเขาประมวลผลข้อความด้วยตนเอง (เช่นถ้าวัตถุมีวิธีการ) ถ้าพวกเขาส่งต่อข้อความไปยังคนอื่น (มอบหมาย / ผู้รับมอบฉันทะ) ถ้าพวกเขาเข้าใจ นั่นคือสิ่งที่ encapsulation เกี่ยวกับนั่นคือสิ่งที่ OO เป็นเรื่องเกี่ยวกับ คุณไม่สามารถแยกความแตกต่างของพร็อกซีจากของจริงได้ตราบใดที่มันตอบสนองตามที่คุณคาดหวัง

คำว่า "ทันสมัย" มากกว่าสำหรับ "การส่งข้อความ" คือ "การกระจายวิธีการแบบไดนามิก" หรือ "การเรียกใช้วิธีการเสมือน" แต่นั่นทำให้คำอุปมาเสียและมุ่งเน้นไปที่กลไก

จุดที่คล้ายกันจะทำยังในการทำความเข้าใจข้อมูลที่เป็นนามธรรมมาเยือนโดยวิลเลียมอาร์คุกและเขาเสนอแบบย่อ, คำจำกัดความที่ทันสมัยของ "วัตถุ" และ "Object Oriented"

การแจกจ่ายแบบไดนามิกของการดำเนินการเป็นลักษณะสำคัญของวัตถุ หมายความว่าการดำเนินการที่จะเรียกใช้เป็นคุณสมบัติแบบไดนามิกของวัตถุเอง ไม่สามารถระบุการดำเนินงานแบบสแตติกและไม่มีวิธีทั่วไปในการดำเนินการใด ๆ ที่จะดำเนินการตามคำขอที่ได้รับยกเว้นโดยการเรียกใช้ สิ่งนี้เหมือนกับฟังก์ชั่นชั้นหนึ่งซึ่งจะถูกส่งแบบไดนามิกเสมอ

ใน Smalltalk-72 ไม่มีแม้แต่วัตถุใด ๆ ! มีเฉพาะสตรีมข้อความที่แยกวิเคราะห์เขียนใหม่และเปลี่ยนเส้นทางใหม่ วิธีมาก่อน (วิธีมาตรฐานในการแยกวิเคราะห์และเปลี่ยนเส้นทางสตรีมข้อความ) มาภายหลังวัตถุ (กลุ่มของวิธีการที่ใช้ร่วมกันบางรัฐส่วนตัว) การสืบทอดมามากในภายหลังและชั้นเรียนได้รับการแนะนำเป็นเพียงวิธีการสนับสนุนการสืบทอด หากกลุ่มวิจัยของเคย์รู้เรื่องต้นแบบแล้วพวกเขาอาจจะไม่เคยแนะนำคลาสในตอนแรก

โปรแกรมเมอร์ทุกคนควรอ่านเข้าใจข้อมูลนามธรรมมาเยือน มันอธิบายในรายละเอียดว่าอะไรคือความแตกต่างระหว่างวัตถุและประเภทข้อมูลนามธรรม เขาให้ตัวอย่างโดยใช้ Java และที่เกี่ยวข้องอย่างยิ่งกับคำถามนี้เพราะทั้งในตัวอย่าง ADT และตัวอย่างวัตถุเขาใช้การสืบทอดการห่อหุ้มและ polymorphism แต่มีเพียงหนึ่งตัวอย่างเท่านั้นที่มุ่งเน้นวัตถุ! กล่าวอีกนัยหนึ่ง: คุณสามารถมีการสืบทอดการห่อหุ้มและ polymorphism คุณสามารถมีทั้งสามอย่างพร้อมกันและยังไม่มี OO

ในทางกลับกันคุณสามารถมี OO ได้โดยไม่มีการสืบทอด เช่นเดียวกับที่ฉันพูดถึงข้างต้น: Smalltalk เวอร์ชันดั้งเดิม (ภาษาที่ออกแบบโดย Alan Kay ผู้ประดิษฐ์คำว่า "การเขียนโปรแกรมเชิงวัตถุ") ไม่มีมรดก

สุดท้าย แต่ไม่ท้ายสุดสนธิสัญญาของออร์แลนโดได้กล่าวถึงการมอบหมายเป็นทางเลือกในการสืบทอดและรูปแบบของการมอบหมายและการสืบทอดที่แตกต่างกันนำไปสู่ประเด็นการออกแบบที่แตกต่างกันภายในพื้นที่การออกแบบของภาษาเชิงวัตถุ (โปรดทราบว่าจริง ๆ แล้วแม้ในภาษาที่สนับสนุนการสืบทอดเช่น Java คนได้รับการสอนให้หลีกเลี่ยงจริง ๆ อีกครั้งบ่งชี้ว่าไม่จำเป็นสำหรับ OO)


คุณสามารถมี "มรดก", "ความแตกต่าง" และ "มรดก" ... methinks มีการพิมพ์ผิดในบางแห่งมี :)
slebetman

1
คำตอบนี้ทำให้ฉันหวังว่าเราจะได้คำตอบที่ 'โปรดปราน' ด้วย
Chan-Ho Suh

คำนิยามของ Alan Kay ล้าสมัยแล้ว OO ต้องการการสืบทอดและถ้าคุณสามารถทำได้ทั้งการทำรันไทม์และการคอมไพล์เวลาคอมไพล์เช่นใน C ++ คุณจะได้รับประสิทธิภาพเทียบเท่ากับ C เช่นกัน
Erik Alapää

ไม่คำจำกัดความของเขาถูกต้อง คุณไม่ต้องการรับมรดกเลยเพื่อเป็น OO ภาษาต้นแบบไม่ได้ใช้การสืบทอดเช่น C ++ และยังคงเป็น OO การสืบทอดจะใช้เพื่อนำโค้ดกลับมาใช้ใหม่เท่านั้นไม่ใช่วิธีที่ดีที่สุดมีหลายภาษาที่ดีกว่าที่มีมิกซ์อินเป็นตัวอย่าง นอกจากนี้ยังไม่มีอะไรเกี่ยวข้องกับการผูกมัดเนื่องจากคุณสามารถมีการแจกจ่ายแบบไดนามิกไม่ได้แม้แต่ใน C ++ เมื่อคุณสามารถใช้วิธีการเสมือนได้ การแสดงไม่มีอะไรเกี่ยวข้องกับสิ่งเหล่านี้ซึ่งเป็นแนวคิดระดับสูงพวกเขาไม่มีประสิทธิภาพ ในความเป็นจริงคุณสามารถใช้การส่งข้อความใน C และเป็น OO
Luiz Felipe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.