User Tools

Site Tools


Sidebar


Introduction


Basic Tutorials


Advance Tutorials


Useful Techniques


Examples

  • Simple Pipe Weight Calculator
  • Unit Convertor

Sidebar

tutorial:oop

This is an old revision of the document!


Object Oriented Programming (OOP)

OOP คืออะไร

Object Oriented Programming (OOP) คือการเขียนโปรแกรมเชิงวัตถุ เป็นการมองสิ่งต่างๆเป็นวัตถุที่ประกอบไปด้วยคุณสมบัติ(Property) และกระบวนการ (Method) หากเราลองมองย้อนกลับไปยุคแรกๆของภาษาคอมพิวเตอร์ เช่น C, Pascal, VB,.. ในยุคนั้น ยังเป็นภาษาระดับสูงแบบธรรมดาที่รันบนหน้าจอ console เท่านั้น หลักการ OOP เพิ่งเกิดขึ้นมาทีหลัง

ผลของการนำ OOP มาประยุกต์ใช้คือการเกิดโปรแกรมในลักษณะที่จับต้องได้ ยกตัวอย่างเช่น Form-Based Application หรือเรียกอีกอย่างว่า Graphic User Interface (GUI) เป็นต้น ภาษาคอมพิวเตอร์ในยุคหลังๆจึงได้ถูกพัฒนาให้รองรับ OOP ได้เป็นพื้นฐาน ยกตัวอย่าง คือ C++, C#, VB. Net, Object Pascal, เป็นต้น

หลักการ OOP จึงสำคัญมากสำหรับการเขียนโปรแกรมสมัยใหม่ เพราะทำให้ code ลดลงและเป็นระเบียบมากขึ้น ง่ายแก่การจัดการ

OOP มีอะไรบ้าง

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

1. Encapsulation

คือ การจำกัดการเข้าถึง Field, Method และ Property ต่างๆ ของ Class นั้นๆ เพื่อไม่ให้เกิดการเรียกใช้งานจากภายนอกอย่างไม่เหมาะสม การจำกัดการเข้าถึงในที่นี้คือการใส่ Access Specifier เหล่านี้ คือ Private, Protected, Public และ Published สำหรับรายละเอียดสามารถอ่านได้จากหัวข้อถัดไป

2. Inheritance

คือ การถ่ายทอด สืบต่อ เช่น Class B สืบต่อความสามารถมาจาก Class A จะทำให้ Class B สามารถทำทุกอย่างที่ Class A ทำได้

3. Polymorphism

คือ การเปลี่ยนรูปร่าง เช่น หาก Class B สืบต่อความสามารถมาจาก Class A จะทำให้ Class B ถูกมองว่าเป็น Class B หรือ Class A ก็ได้ในขณะเดียวกัน

4. Overriding

คือ การปรับเปลี่ยน เช่น หาก Class B สืบต่อความสามารถมาจาก Class A แล้ว สำหรับ Class B เราสามารถปรับเปลี่ยนความสามารถที่ได้รับมาจาก Class A เพื่อให้ทำงานได้เหมาะสมขึ้น


Class and Object

Class และ Object คือ ผลิตผลจากการนำ OOP มาประยุกต์ใช้ ทั้งคู่มีความคล้ายคลึงกันมาก รูปแบบในการสร้าง Class และ Object มีดังนี้

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 ยังมีข้อแตกต่างกัน

Classes and Instances

หากเราจำเป็นต้องสร้างโค๊ดเกี่ยวกับอะไรสักอย่างหนึ่ง ยกตัวอย่าง เช่น รถยนต์ โดยที่รถยนต์ที่เราจะสร้างขึ้นมานั้น มีหลายคัน คงจะลำบากไม่ใช่น้อยที่จะต้องมาเขียนโค๊ดสำหรับรถยนต์เหล่านั้นไปทีละตัวจนหมด ปัญหาเหล่านี้จะหมดไป หากเรารู้จักการเขียน 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
ในโปรแกรม Turbo Pascal สมัยก่อน Object ถูกใช้ทำหน้าที่เหมือนกันกับ Class แต่ต่อมาภายหลัง เมื่อมีการเปิดตัว Delphi จึงได้มีการคิดค้น Class ขึ้นมาเพื่อใช้งานแทน Object แต่อย่างไรก็ตาม Object ก็ยังเป็นที่นิยมใช้กันมาปกติจนถึงปัจจุบัน สิ่งที่แตกต่างกัน ระหว่าง Class กับ Object คือ

  • Object ใช้หน่วยความจำแบบ Stack ส่วน Class ใช้หน่วยความจำแบบ Heave นั่นทำให้ทุกครั้งที่มีการสร้าง Instance จาก Class ขึ้นมาใช้งาน จำเป็นต้องมีการกำจัด Instance เมื่อใช้งานเสร็จเสมอ เพื่อไม่ให้เกิดปัญหา Memory Leak
  • Object ใช้การอ้างอิงตัวแปรแบบ Value ส่วน Class ใช้การอ้างอิงตัวแปรแบบ Reference เพื่อให้เห็นภาพ ขอยกตัวอย่าง หากให้ A,B เป็น Object เมื่อใช้คำสั่ง B:=A ; จะหมายถึง มี B เกิดขึ้นมาอีกหนึ่งตัวซึ่งเกิดจากการคัดลอก A ผลก็คือหากเราทำอะไรกับ B ก็จะไม่ส่งผลกับ A เพราะเป็นคนละตัวกัน แต่หากเราให้ A,B เป็น Instance ของ Class เมื่อใช้คำสั่ง B:=A ; จะกลายเป็นว่า B อ้างอิงไปที่ A ไม่ได้เกิดการคัดลอกใดๆ ทีนี้หากเราทำการเปลี่ยนแปลง B จะหมายถึงการเปลี่ยนแปลง A ด้วยเช่นกัน

การสร้าง Class เริ่มต้น ทำได้ดังนี้

Type
   TMyClass = class
     Item:integer;
     Procedure DoSomething;     
   end;

การสร้าง Class ต่อจาก Class อื่น หรือเรียกว่าการสืบทอด (Inheritance) ทำได้ดังนี้

Type
   TMyClass = class(TBaseClass)
     Item:integer;
     Procedure DoSomething;     
   end;

องค์ประกอบของ Class แบบละเอียด มีดังนี้

Type
  TMyItem = class(TPersistent);
   private
     FName:string;
     FValue:integer; 
     function GetIsOK:boolean;  
   protected
     procedure DoSomeThing1; 
     procedure DoSomeThing2; virtual;
   public
     constructor Create; override;
     destructor Destroy; override;
     procedure Assign(Source: TPersistent); override;
     property IsOK:boolean read GetIsOK; 
     property ValueX:integer read GetValueX write SetValueX;
   published
     property Name:string read FName write FName;
     property Value:integer read FValue write FValue default 0;

Ancestor Class หรือ Super Class คือ class ต้นแบบ จากตัวอย่าง คือ TPersistent

Field Parameters คือ ส่วนที่ถูกประกาศเป็นตัวแปรคล้ายกับการประกาศ var จากตัวอย่างข้างบน คือ FName และ FValue ตัวแปรเหล่านี้มักถูกประกาศเพื่อใช้เก็บค่าสำหรับ Property

Constructor and Destructor

คือ Procedure ชนิดหนึ่ง แต่มีความสำคัญต่อ class มาก จึงต้องเขียนให้มีชื่อเฉพาะเป็นของตนเอง Constructor จะที่ถูกเรียกเพื่อใช้สร้าง Instance โดยทำการจัดสรรหน่วยความจำให้เหมาะสม ส่วน Destructor จะถูกเรียกเพื่อทำลาย Instance แล้วคืนหน่วยความจำ

Properties

คือคุณสมบัติของ Instance ประกอบไปด้วย Getter (คำสั่งหลัง read) และ Setter (คำสั่งหลัง write)

เพื่อเป็นการอธิบายให้เห็นภาพ จะขอยกตัวอย่าง

property ValueX:integer read GetValueX write SetValueX;

จากตัวอย่างดังกล่าว Getter คือ GetValueX ส่วน Setter คือ SetValueX
Getter จะถูกเรียกใช้งาน เมื่อมีการเรียกต่าจาก Property ดังเช่น

writeln(ValueX);

Setter จะถูกเรียกใช้งาน เมื่อมีการ Assign ค่าใส่ Property เช่น

ValueX:=12;

ทำไมต้องมี Getter Setter ให้ยุ่งยาก แทนที่จะใช้ var หรือ Field อย่างเดียว? ประโยชน์ของการใช้งาน Property มีดังนี้ครับ

  • ใช้คัดกรองตัวแปร บางครั้งเรารับค่าเพื่อการคำนวณในช่วง 0-100 เท่านั้น หากผู้ใช้ใส่ค่าเกินกว่าค่าดังกล่าวมา จะสามารถคัดกรองให้เป็นค่าที่อยู่ในช่วง 0-100 แทนได้
  • เพื่อให้ค่าของ Property ได้มีการ update ตลอดเวลา โดยเฉพาะหาก property ของเรา ขึ้นอยู่กับค่าอื่น เมื่อใดที่มีการเปลี่ยนค่า ก็จะมีการ update ค่า property เราด้วยเสมอ
  • published properties ที่มาจาก TPersistent Class สามารถใช้งานกับ RTTI Controls ได้ เพื่อลดการเขียนโค๊ดในการเชื่อมต่อกับ Controls สำหรับ GUI Applications

รูปแบบการเขียน Property มีหลักๆดังนี้

  • Property ที่มี Getter, Setter เป็น Field
property Value:integer read FValue write Value;
  • property ที่มี Getter, Setter เป็น Procedure/Function ซึ่งโดยปกติ Getter จะเป็น Function ส่วน Setter จะเป็น Procedure
property ValueX:integer read GetValueX write SetValueX;
function GetValueX:integer;
procedure SetValueX(Value:integer);
  • Property ที่แสดงค่าได้อย่างเดียว (ReadOnly)
property IsOK:boolean read GetIsOK;



Access Modifiers

คือ private, protected, public และ published โดยแต่ละตัวกำหนดความสามรถในการเข้าถึง Field, Procedure, Function หรือ Property ที่อยู่ภายใต้ สรุปได้ดังนี้

Access Modifier Descriptions
private มองเห็นได้เฉพาะที่อยู่ใน Unit เดียวกันกับ Class นี้เท่านั้น
protect มองเห็นได้เฉพาะ Derived-Class เท่านั้น
public มองเห็นได้จากทุกที่ที่ uses Unit นี้
published เหมือนกันกับ Public แต่จะสร้าง Run Time Type Information (RTTI) ด้วย

Example-1: Property Getter Setter Test

Example-1: Property Getter Setter Test

ตัวอย่าง การสร้าง Class ที่มี Properties 2 ตัว คือ ValueX กับ ValueY โดยที่ ValueY นั้นเกิดจากการนำค่า ValueX คูณด้วย 2 จึงต้องเป็นแบบ ReadOnly
ข้อสังเกต: ValueY เกิดจากการคำนวณ ValueX ดังนั้นหากมีการเปลี่ยนแปลง ValueX ค่าของ ValueY จะมีการ Update ผ่าน Getter

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.

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!!!
 
tutorial/oop.1546659427.txt.gz · Last modified: 2019/01/05 10:37 by admin