This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision Last revision Both sides next revision | ||
tutorial:oop [2018/12/25 15:41] admin |
tutorial:oop [2019/01/05 14:09] admin |
||
---|---|---|---|
Line 9: | Line 9: | ||
=====OOP มีอะไรบ้าง===== | =====OOP มีอะไรบ้าง===== | ||
- | โดยทั่วไป หลักการ OOP ในหลายๆภาษาจะคล้ายคลึงกัน แตกต่างกันเพียงแค่ Syntax เท่านั้น โดยหลักการดังกล่าว มักจะประกอบไปด้วยส่วนต่างๆดังต่อไปนี้ | + | โดยทั่วไป หลักการ OOP ในหลายๆภาษาจะคล้ายคลึงกัน โดยหลักการดังกล่าวได้ถูกหล่อหลอมรวมกันจนกลายมาเป็น Class และ Object นั่นเอง อธิบายได้แบบสั้นๆง่ายๆดังนี้ (เนื่องจาก Class และ Object คล้ายกัน เนื่องจากเกิดมาจากหลักการ OOP เหมือนกัน ดังนั้นจะขอนำแค่ Class มายกตัวอย่าง) |
- | ====2. Encapsulation==== | + | ====1. Encapsulation==== |
- | ====3. Inheritance==== | + | คือ การจำกัดการเข้าถึง Field, Method และ Property ต่างๆ ของ Class นั้นๆ เพื่อไม่ให้เกิดการเรียกใช้งานจากภายนอกอย่างไม่เหมาะสม การจำกัดการเข้าถึงในที่นี้คือการใส่ Access Specifier เหล่านี้ คือ Private, Protected, Public และ Published สำหรับรายละเอียดสามารถอ่านได้จากหัวข้อถัดไป |
- | ====4. Polymorphism==== | + | ====2. Inheritance==== |
- | ====5. Overriding==== | + | คือ การถ่ายทอด สืบต่อ เช่น Class B สืบต่อความสามารถมาจาก Class A จะทำให้ Class B สามารถทำทุกอย่างที่ Class A ทำได้ |
- | ====6. Overloading==== | + | ====3. Polymorphism==== |
+ | คือ การเปลี่ยนรูปร่าง เช่น หาก Class B สืบต่อความสามารถมาจาก Class A จะทำให้ Class B ถูกมองว่าเป็น Class B หรือ Class A ก็ได้ในขณะเดียวกัน | ||
+ | ====4. Overriding==== | ||
+ | คือ การปรับเปลี่ยน เช่น หาก Class B สืบต่อความสามารถมาจาก Class A แล้ว สำหรับ Class B เราสามารถปรับเปลี่ยนความสามารถที่ได้รับมาจาก Class A เพื่อให้ทำงานได้เหมาะสมขึ้น | ||
- | =====1. Classes and Instances===== | + | \\ |
- | หากเราจำเป็นต้องสร้างโค๊ดเกี่ยวกับอะไรสักอย่างหนึ่ง ยกตัวอย่าง เช่น รถยนต์ โดยที่รถยนต์ที่เราจะสร้างขึ้นมานั้น มีหลายคัน คงจะลำบากไม่ใช่น้อยที่จะต้องมาเขียนโค๊ดสำหรับรถยนต์เหล่านั้นไปทีละตัวจนหมด ปัญหาเหล่านี้จะหมดไป หากเรารู้จักการเขียน Class และ Object(Instance) \\ \\ | + | ---- |
+ | ======Class and Object====== | ||
+ | Class และ Object คือ ผลิตผลจากการนำ OOP มาประยุกต์ใช้ ทั้งคู่มีความคล้ายคลึงกันมาก รูปแบบในการสร้าง Class และ Object มีดังนี้ | ||
- | **Classes** คือ ต้นแบบ เปรียบเสมือนการออกแบบรถยนต์ว่าควรประกอบไปด้วยคุณสมบัติอะไรบ้าง เช่น โครงสร้าง เครื่องยนต์ ช่วงล่าง ระบบส่งกำลัง ตัวถัง เป็นต้น ทั้งหมดที่กล่าวมานี้ เราเรียกว่า Property แค่นั้นยังไม่พอ รถยนต์ควรจะมีความสามารถอะไรบ้าง นั่นคือ ขับได้ วิ่งไปมาด้วยความรวดเร็วได้ เบรคได้ เราเรียกสิ่งนี้ว่า Method | ||
- | **Objects (Instances)** คือ ผลิตภัณท์ที่เกิดจากต้นแบบ (Class) เช่น เราผลิตรถยนต์ขึ้นมาใช้งานจริง 5 คัน ซึ่งใน 5 คันนี้ อาจมี Property ที่ต่างกันไป แต่ทุกคันมี Method ที่เหมือนกัน เราเรียกรถยนต์เหล่านี้ว่า Object หรือ Instance เป็นต้น แต่เนื่องจากคำว่า Object มีใช้ในภาษา Pascal เช่นกัน และเป็นคำเฉพาะซึ่งหมายถึงการสร้างวัตถุที่เป็นต้นแบบขึ้นมาเหมือนกัน (คล้าย Class) ดังนั้นต่อไปนี้จะขอใช้คำว่า Instance แทน | + | Type |
+ | TMyClass = class | ||
+ | Item:integer; | ||
+ | Procedure DoSomething; | ||
+ | end; | ||
+ | |||
+ | Type | ||
+ | TMyObject = object | ||
+ | Item:integer; | ||
+ | Procedure DoSomething; | ||
+ | end; | ||
+ | |||
+ | จริงๆแล้ว ทั้งสองอย่างนี้มีข้อแตกต่างกันอยู่ และถูกใช้งานต่างกัน แต่จะขอพูดถึงรายละเอียดของ Object ก่อน ว่าสามารถทำอะไรได้บ้าง จากนั้นจึงโยงไปสู่รายละเอียดของ Class ในภายหลัง | ||
+ | |||
+ | =====Object===== | ||
+ | Object เป็น Structural Type คล้ายกันกับ Record เพียงแต่มี Property และ Method เพิ่มเข้ามา และรองรับหลักการ OOP ที่กล่าวมาแล้วข้างต้นทั้งหมด Object ถือกำเนิดขึ้นมาก่อนตั้งแต่สมัยของ Turbo Pascal ต่อมาภายหลัง เมื่อมีการสร้าง Delphi ขึ้นมาใช้แทน เป็นเหตุให้มีการคิดค้น Class ขึ้นมาใช้งานด้วยเช่นกัน | ||
+ | |||
+ | อย่างไรก็ตาม Class ยังมีข้อแตกต่างกัน | ||
+ | |||
+ | =====Class===== | ||
+ | หากเราจำเป็นต้องสร้างโค๊ดเกี่ยวกับอะไรสักอย่างหนึ่ง ยกตัวอย่าง เช่น รถยนต์ โดยที่รถยนต์ที่เราจะสร้างขึ้นมานั้น มีหลายคัน คงจะลำบากไม่ใช่น้อยที่จะต้องมาเขียนโค๊ดสำหรับรถยนต์เหล่านั้นไปทีละตัวจนหมด ปัญหาเหล่านี้จะหมดไป หากเรารู้จักการเขียน Class \\ \\ | ||
+ | |||
+ | **Class** คือ ต้นแบบ เปรียบเสมือนการออกแบบรถยนต์ว่าควรประกอบไปด้วยคุณสมบัติอะไรบ้าง เช่น โครงสร้าง เครื่องยนต์ ช่วงล่าง ระบบส่งกำลัง ตัวถัง เป็นต้น ทั้งหมดที่กล่าวมานี้ เราเรียกว่า Property แค่นั้นยังไม่พอ รถยนต์ควรจะมีความสามารถอะไรบ้าง นั่นคือ ขับได้ วิ่งไปมาด้วยความรวดเร็วได้ เบรคได้ เราเรียกสิ่งนี้ว่า Method | ||
+ | |||
+ | **Instance** คือ ผลิตภัณท์ที่เกิดจากต้นแบบ (Class) เช่น เราผลิตรถยนต์ขึ้นมาใช้งานจริง 5 คัน ซึ่งใน 5 คันนี้ อาจมี Property ที่ต่างกันไป แต่ทุกคันมี Method ที่เหมือนกัน เราเรียกรถยนต์เหล่านี้ว่า Object หรือ Instance เป็นต้น แต่เนื่องจากคำว่า Object มีใช้ในภาษา Pascal เช่นกัน และเป็นคำเฉพาะซึ่งหมายถึงการสร้างวัตถุที่เป็นต้นแบบขึ้นมาเหมือนกัน (คล้าย Class) ดังนั้นต่อไปนี้จะขอใช้คำว่า Instance แทน | ||
**__หมายเหตุ__** - **Object** สำหรับภาษา Pascal หมายถึงการสร้างวัตถุที่มีทั้งคุณสมบัติ (Property) และกระบวนการ (method) เหมือนกันกับ Class เพียงแต่ Class นั้นเพิ่งเกิดมาในภายหลัง โดย Object จะคล้ายกับ Record ที่มี Property กับ Method นั่นเอง หรือ ที่เรียกว่า Advance Record \\ | **__หมายเหตุ__** - **Object** สำหรับภาษา Pascal หมายถึงการสร้างวัตถุที่มีทั้งคุณสมบัติ (Property) และกระบวนการ (method) เหมือนกันกับ Class เพียงแต่ Class นั้นเพิ่งเกิดมาในภายหลัง โดย Object จะคล้ายกับ Record ที่มี Property กับ Method นั่นเอง หรือ ที่เรียกว่า Advance Record \\ | ||
Line 90: | Line 118: | ||
ValueX:=12; | ValueX:=12; | ||
| | ||
- | ทำไมต้องมี Getter Setter ให้ยุ่งยาก แทนที่จะใช้ var อย่างเดียว? ประโยชน์ของมันมีดังนี้ครับ | + | ทำไมต้องมี Getter Setter ให้ยุ่งยาก แทนที่จะใช้ var หรือ Field อย่างเดียว? ประโยชน์ของการใช้งาน Property มีดังนี้ครับ |
*ใช้คัดกรองตัวแปร บางครั้งเรารับค่าเพื่อการคำนวณในช่วง 0-100 เท่านั้น หากผู้ใช้ใส่ค่าเกินกว่าค่าดังกล่าวมา จะสามารถคัดกรองให้เป็นค่าที่อยู่ในช่วง 0-100 แทนได้ | *ใช้คัดกรองตัวแปร บางครั้งเรารับค่าเพื่อการคำนวณในช่วง 0-100 เท่านั้น หากผู้ใช้ใส่ค่าเกินกว่าค่าดังกล่าวมา จะสามารถคัดกรองให้เป็นค่าที่อยู่ในช่วง 0-100 แทนได้ | ||
- | *เพื่อให้ค่าของ Property ได้มีการ update ตลอดเวลา โดยเฉพาะหาก property ของเรา ขึ้นอยู่กับค่าอื่น เมื่อใดที่มีการเปลี่ยนค่า ก็จะมีการ update ค่า property เราด้วยเสมอ\\ | + | *เพื่อให้ค่าของ Property ได้มีการ update ตลอดเวลา โดยเฉพาะหาก property ของเรา ขึ้นอยู่กับค่าอื่น เมื่อใดที่มีการเปลี่ยนค่า ก็จะมีการ update ค่า property เราด้วยเสมอ |
+ | *published properties ที่มาจาก TPersistent Class สามารถใช้งานกับ RTTI Controls ได้ เพื่อลดการเขียนโค๊ดในการเชื่อมต่อกับ Controls สำหรับ GUI Applications\\ | ||
รูปแบบการเขียน Property มีหลักๆดังนี้ | รูปแบบการเขียน Property มีหลักๆดังนี้ | ||
Line 99: | Line 128: | ||
property Value:integer read FValue write Value; | property Value:integer read FValue write Value; | ||
- | *property ที่มี Getter, Setter เป็น Procedure/Function | + | *property ที่มี Getter, Setter เป็น Procedure/Function ซึ่งโดยปกติ Getter จะเป็น Function ส่วน Setter จะเป็น Procedure |
property ValueX:integer read GetValueX write SetValueX; | property ValueX:integer read GetValueX write SetValueX; | ||
+ | function GetValueX:integer; | ||
+ | procedure SetValueX(Value:integer); | ||
*Property ที่แสดงค่าได้อย่างเดียว (ReadOnly) | *Property ที่แสดงค่าได้อย่างเดียว (ReadOnly) | ||
Line 118: | Line 149: | ||
|published| เหมือนกันกับ Public แต่จะสร้าง Run Time Type Information (RTTI) ด้วย | | |published| เหมือนกันกับ Public แต่จะสร้าง Run Time Type Information (RTTI) ด้วย | | ||
+ | <hidden Example-1: Property Getter Setter Test> | ||
+ | **ตัวอย่าง** การสร้าง Class ที่มี Properties 2 ตัว คือ ValueX กับ ValueY โดยที่ ValueY นั้นเกิดจากการนำค่า ValueX คูณด้วย 2 จึงต้องเป็นแบบ ReadOnly \\ | ||
+ | __ข้อสังเกต__: ValueY เกิดจากการคำนวณ ValueX ดังนั้นหากมีการเปลี่ยนแปลง ValueX ค่าของ ValueY จะมีการ Update ผ่าน Getter\\ | ||
+ | <sxh delphi;> | ||
+ | program TestGetterSetter; | ||
+ | |||
+ | type | ||
+ | |||
+ | { TMyClass } | ||
+ | |||
+ | TMyClass = class | ||
+ | private | ||
+ | FValueX:integer; | ||
+ | function GetValueY: integer; | ||
+ | public | ||
+ | Constructor Create; | ||
+ | destructor destroy; override; | ||
+ | property ValueX:integer read FVAlueX write FValueX; | ||
+ | property ValueY:integer read GetValueY; | ||
+ | end; | ||
+ | |||
+ | { TMyClass } | ||
+ | |||
+ | function TMyClass.GetValueY: integer; | ||
+ | begin | ||
+ | result:=2*ValueX; | ||
+ | end; | ||
+ | |||
+ | constructor TMyClass.Create; | ||
+ | begin | ||
+ | FValueX:=5; | ||
+ | writeln('Instance has been created!!!'); | ||
+ | |||
+ | end; | ||
+ | |||
+ | destructor TMyClass.destroy; | ||
+ | begin | ||
+ | writeln('Instance has been destroyed!!!'); | ||
+ | inherited destroy; | ||
+ | end; | ||
+ | |||
+ | var | ||
+ | MyClass:TMyClass; | ||
+ | |||
+ | begin | ||
+ | MyClass:=TMyClass.Create; | ||
+ | writeln('MyClass.ValueX = ',MyClass.ValueX); | ||
+ | writeln('MyClass.ValueY = ',MyClass.ValueY); | ||
+ | writeln('Change ValueX to 50'); | ||
+ | MyClass.ValueX:=50; | ||
+ | writeln('MyClass.ValueX = ',MyClass.ValueX); | ||
+ | writeln('MyClass.ValueY = ',MyClass.ValueY); | ||
+ | MyClass.Free; | ||
+ | readln(); | ||
+ | end. | ||
+ | </sxh> | ||
+ | \\ | ||
+ | Compiled Result: | ||
+ | Instance has been created!!! | ||
+ | MyClass.ValueX = 5 | ||
+ | MyClass.ValueY = 10 | ||
+ | Change ValueX to 50 | ||
+ | MyClass.ValueX = 50 | ||
+ | MyClass.ValueY = 100 | ||
+ | Instance has been destroyed!!! | ||
+ | |||
+ | </hidden> |