User Tools

Site Tools


tutorial:record

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
tutorial:record [2019/01/10 20:01]
admin
tutorial:record [2019/01/28 10:14] (current)
admin
Line 55: Line 55:
 ปกติแล้ว Record จะมีแค่ Field Variable อยู่ภายใน แต่ยังมี Record อีกประเภทหนึ่งที่มี Method และ Property ได้ เรียกว่า Advanced Record \\ ปกติแล้ว Record จะมีแค่ Field Variable อยู่ภายใน แต่ยังมี Record อีกประเภทหนึ่งที่มี Method และ Property ได้ เรียกว่า Advanced Record \\
  
-Advanced Record ถูกสร้างขึ้นเพื่อให้มีความสามารถทางด้าน Object Oriented Programming ​เช่นเดียวกับ Object จะเรียกได้ว่า Advanced Record กับ Object นั้นเหมือนกันแทบทั้งหมดก็ว่าได้ ​\\+Advanced Record ถูกสร้างขึ้นเพื่อให้มีความสามารถทางด้าน Object Oriented Programming \\
  
 การประกาศ Advanced Record จำเป็นต้องมี Compiler Directive ต่อไปนี้ การประกาศ Advanced Record จำเป็นต้องมี Compiler Directive ต่อไปนี้
Line 61: Line 61:
   {$modeSwitch advancedRecords}   {$modeSwitch advancedRecords}
   ​   ​
-จากนั้น เราก็สามารถประกาศ Record ​ให้มีหน้าตาคล้ายกับ Object ​ได้แบบนี้+จากนั้น เราก็สามารถประกาศ ​Procedure/​Function บน ​Record ได้ดังนี้
  
   Type   Type
Line 136: Line 136:
 ---- ----
 =====Object===== =====Object=====
-ถูกสร้างขึ้นมาตั้งแต่สมัยที่ยังใช้ Turbo Pascal โดยออกแบบให้เป็นไปตามหลักการ Object Oriented Programming (OOP) ลักษณะการใช้งานโดยทั่วไปจะคล้ายกับ Advanced Record \\ \\+ถูกสร้างขึ้นมาตั้งแต่สมัยที่ยังใช้ Turbo Pascal โดยออกแบบให้เป็นไปตามหลักการ Object Oriented Programming (OOP) ลักษณะการใช้งานโดยทั่วไปจะเหมือนกันกับ Advanced Record \\ \\ 
 +สาเหตุที่มีให้ใช้ทั้ง Object และ Advanced Record นั้น เพราะว่าภายหลังจากที่ Delphi เปิดตัว ได้มีการนำ Class มาใช้แทน Object และผลักดันให้ เรียก Object ว่าเป็น Advanced Record แทน (อันนี้ผมเข้าใจว่า เพราะคำว่าว่า Object ในภาษาทั่วไป คือ instance ซึ่งแปลว่าผลิตภัณท์ที่เกิดจากต้นแบบ (Class) ซึ่งอาจสร้างความสับสนให้ผู้ใช้ได้) ทีนี้ทางฝั่งของ FPC ซึ่งมีการออกแบบให้โค๊ดทั้งหลายคล้ายคลึงกับทั้งทาง Turbo Pascal และ Delphi อยู่แล้วนั้น ได้ตัดสินใจเก็บ Object ไว้ เพื่อให้ยัง Compatible กับ Turbo Pascal อยู่นั่นเอง แต่ถึงอย่างไรทั้งสอง ก็ถูกใช้งานเหมือนกัน
  
 การประกาศ Object อย่างง่าย ทำได้ดังนี้ การประกาศ Object อย่างง่าย ทำได้ดังนี้
Line 148: Line 149:
      end;      end;
  
-อย่างไรก็ตาม ในการนำ Object ใช้งานจริงนั้น ไม่ได้มีเพียงแค่ ​Methods ​กับ ​Variables ​แต่ยังมีส่วนประกอบอื่นๆอีกมากมาย+อย่างไรก็ตาม ในการนำ Object ใช้งานจริงนั้น ไม่ได้มีเพียงแค่ ​Field กับ ​Method ดังที่เห็นในตัวอย่าง ​แต่ยังมีส่วนประกอบอื่นๆอีกมากมาย ​อาทิเช่น Property, Access Specifiers เป็นต้น นอกจากนี้ Object ยังสามารถถ่ายทอดความสามารถ (Inheritance) ไปสู่ Object อื่นได้ ซึ่งรายละเอียดเหล่านี้จะขอนำไปกล่าวในเนื้อหาของ Class ต่อไป เพราะ Class กับ Object ต่างมีหลักการคล้ายคลึงกัน\\ 
 + 
 ตัวอย่างการสร้าง Object แบบละเอียด ตัวอย่างการสร้าง Object แบบละเอียด
 <sxh delphi;> <sxh delphi;>
Line 157: Line 159:
      ​FValue:​integer; ​      ​FValue:​integer; ​
      ​function GetIsOK:​boolean;  ​      ​function GetIsOK:​boolean;  ​
-   ​protected 
-     ​procedure DoSomeThing1; ​ 
    ​public    ​public
-     ​procedure ​DoSomeThing2;+     ​procedure ​DoSomeThing;
      ​property Name:string read FName write FName;      ​property Name:string read FName write FName;
      ​property Value:​integer read FValue write FValue default 0;      ​property Value:​integer read FValue write FValue default 0;
Line 169: Line 169:
 \\  \\ 
 จากตัวอย่างโค๊ดข้างบน จะอธิบายส่วนประกอบต่างๆทีละส่วนดังนี้ จากตัวอย่างโค๊ดข้างบน จะอธิบายส่วนประกอบต่างๆทีละส่วนดังนี้
-====Access ​Specifiers====  +====Access ​Modifier====  
-คือ private, protected, public ​และ ​published ​โดยแต่ละตัวกำหนดความสามรถในการเข้าถึง Field, Procedure, Function หรือ Property ที่อยู่ภายใต้ สรุปได้ดังนี้+ 
 +  type 
 +    TObj = object 
 +      private 
 +        { private declarations } 
 +      public 
 +        { public declarations } 
 +    end; 
 +  ​ 
 +คือ private และ ​public ​โดยแต่ละตัวกำหนดความสามรถในการเข้าถึง Field, Procedure, Function หรือ Property ที่อยู่ภายใต้ สรุปได้ดังนี้
  
 ^  Access Modifier ​ ^  Descriptions ​ ^  ^  Access Modifier ​ ^  Descriptions ​ ^ 
 |private| มองเห็นได้เฉพาะที่อยู่ใน Unit เดียวกันกับ Object นี้เท่านั้น | |private| มองเห็นได้เฉพาะที่อยู่ใน Unit เดียวกันกับ Object นี้เท่านั้น |
-|protect| มองเห็นได้เฉพาะ Object ที่สืบทอดมาจาก Object ดังกล่าวเท่านั้น | 
 |public| มองเห็นได้จากทุกที่ที่มีการ uses Unit นี้ | |public| มองเห็นได้จากทุกที่ที่มีการ uses Unit นี้ |
 +|ไม่ระบุ| หมายถึง Public |
 ====Field Parameters==== ​ ====Field Parameters==== ​
 คือ ส่วนที่ถูกประกาศเป็นตัวแปรคล้ายกับการประกาศ var จากตัวอย่างข้างบน คือ FName และ FValue ตัวแปรเหล่านี้มักถูกประกาศเพื่อใช้เก็บค่าสำหรับ Property \\ คือ ส่วนที่ถูกประกาศเป็นตัวแปรคล้ายกับการประกาศ var จากตัวอย่างข้างบน คือ FName และ FValue ตัวแปรเหล่านี้มักถูกประกาศเพื่อใช้เก็บค่าสำหรับ Property \\
Line 181: Line 190:
  
 ====Properties==== ​ ====Properties==== ​
-คือ คุณสมบัติของ Object ​ะกอบไปด้วย Getter (คำสั่งหลัง read) และ ​Setter (คำสั่งหลัง write)\\ \\ +คือ คุณสมบัติของ Object ​โดยยละเอจะขอกล่าวในหัวข้อ Class อีกที\\ \\
-พื่เป็นการอธิบาให้เห็นภาพ ​จะขอัวอย่าง+
  
-  property ValueX:​integer read GetValueX write SetValueX; 
  
-จากตัวอย่างดังกล่าว Getter คือ GetValueX ส่วน Setter คือ SetValueX \\ 
-Getter จะถูกเรียกใช้งาน เมื่อมีการเรียกใช้ค่าของ Property ดังเช่น 
  
-  writeln(ValueX);​ 
-  ​ 
-Setter จะถูกเรียกใช้งาน เมื่อมีการใส่ค่าให้ Property เช่น 
  
-  ValueX:=12; +<hidden Example-3Object without Properties>​ 
-   +**ัวอย่** กรสร้าง Object ทรงบอก Cylinder เพรับค่า ​รัศมีวงกลม (Radius) กับ ควมสูง (Height) เข้ามาเป็น Input \\ จากน้น 
-ทำไมงมี Getter Setter ให้่งาก ​แทนที่จใช้ var หรือ ​Field อย่างเด? ประโยชน์ของการใช้งาน Property ​ีดังนี้ครับ +จึงนำมาำนวณพื้นที่ฐาน (Area) และปิมาตร (Volume) \\ \\ 
-  ​*ใชรองตัวแปร บางครั้งเรารบค่เพื่อการคำนวณ่วง 0-100 ่านั้น ​กผู้ใช้ใส่ค่าเกิว่าค่าังกล่าวมา จะมารถคดกรอให้เป็นค่าี่อยู่ใช่วง 0-100 แทนได้ +__ขอสงเต__: ​ตัวอย่างนี้ แสดให้ห็นปญหการไม่ใช้ Property จะสังเกตว่า ​ตอนแรกนั้นเราใส่ค่า ​Radius = 2 และ Height = 10 แล้วสั่งคำนวณค่าจาก CalculateArea,​ CalculateVolume จะได้ค่า ​Area, Volume มาตามปกติ \\ \\ แต่หลังจานั้น เมื่อเปี่ยนค่า ​Radius เป็น 10 แล้ลองไ่เรียก CalculateArea,​ CalculateVolume เมื่อเรียกดูค่า Area, Volume ​จะเห็นว่ังเป็นค่าเดิม เพราะไม่ได้มการ Update คา Area, Volume เหมือนตอแรก\\ \\ สรุปได้ว่า ​ื่อมีการเปลี่ยนค่า ​Radius หรือ Height จะตองมีการเรียก CalculateArea,​ CalculateVolume ทุกครั้ง จึงจะได้ค่า Area, Volume ที่ถูก้อง ​ลองจินตนาการถึงการขียนโปรแกรมจริงๆาหากเรามี Input กับ Output ที่มากขึ้นในระดับ ​10-20 ตัว ซึ่งแต่ละตัวมีการคำนวณค่าที่ซับซ้น ทีผ่าน Procedure/​Function หลายตัว คงป็นการลำบากที่จะต้องมาียก Procedure/​Function ​ล่ั้น ทุกรั้งที่มีการ update ค่า ​Input นี่จึงเป็นเหตุผลหนึ่ง ที่เราควรใชงาน Property แทนที่ตัแปร ​ Input/​Output พวกนี้ ​ำหรับการเปลี่ยนาใช้ Property ให้ดูได้จาก Example-4 
-  *ื่อให้ค่าง Property ได้มีการ ​update ​ตลอเวา โดยเฉพาะหาก ​property ของเรา ขึ้นอยู่กับค่าอ่น เมื่อใดที่มีการเนค่า ก็จะมีการ update ค่า ​property ​เรา้วยเสม+  
 +<sxh delphi;​highlight:​ []> 
 +program Cylinder_Without_Properties;​
  
 +type
  
-รูปแบบการเขียน Property มีหลักๆดังนี้ +  { TMyCylinder }
-  *Property ที่มี Getter, Setter เป็น Field+
  
-  ​property Value:integer read FValue write FValue;+  ​TMyCylinder = Object 
 +    Radius:real;   //​Input 
 +    Height:​real; ​  //​Input 
 +    Area:​real; ​    //​Output 
 +    Volume:​real; ​  //​Output 
 +    procedure CalculateArea;​ 
 +    procedure CalculateVolume;​ 
 +    procedure ShowData; 
 +  end;
  
-  *property ที่มี Getter, Setter เป็น Procedure/​Function ซึ่งโดยปกติ Getter จะเป็น Function ส่วน Setter จะเป็น Procedure+{ TMyCylinder }
  
-  property ValueX:​integer read GetValueX write SetValueX+procedure TMyCylinder.CalculateArea; 
-  ​function GetValueX:integer+begin 
-  ​procedure SetValueX(Value:​integer);+  ​Area:=system.pi*(Radius*Radius)
 +end;
  
-  ​*Property ที่แสดงค่าได้อย่างเดียว (ReadOnly)+procedure TMyCylinder.CalculateVolume;​ 
 +begin 
 +  Volume:​=Area*Height; 
 +end;
  
-  property IsOK:​boolean read GetIsOK;+procedure TMyCylinder.ShowData;​ 
 +begin 
 +  writeln('​Radius = ',​Radius);​ 
 +  writeln('​Area = ',​Area);​ 
 +  writeln('​Volume = ',​Volume);​ 
 +end;
  
 +var
 +  Cylinder:​TMyCylinder;​
  
 +begin
 +  Cylinder.Radius:​=2;​ //Set Radius = 2
 +  Cylinder.Height:​=10;​ //Set Radius = 2
 +  Cylinder.CalculateArea;​ //Calculate Area of Cylinder
 +  Cylinder.CalculateVolume;​ //Calculate Volume of Cylinder
 +  Cylinder.ShowData; ​ //Show the results
 +
 +  Cylinder.Radius:​=10;​ //Change Radius to 10
 +  Cylinder.ShowData; ​ //Show the result without calling CalculateArea
 +
 +  readln;
 +end.   
 +</​sxh> ​
 +</​hidden>​
   ​   ​
 +<hidden Example-4: Object Properties>​
 +**ตัวอย่าง** การสร้าง Object ทรงกระบอก Cylinder เพื่อรับค่า รัศมีวงกลม (Radius) กับ ความสูง (Height) เข้ามาเป็น Input \\ จากนั้น
 +จึงนำมาคำนวณพื้นที่ฐาน (Area) และปริมาตร (Volume) \\ \\
 +__ข้อสังเกต__:​ ตัวอย่างนี้ ใช้ Property แทนตัวแปร Output และเปลี่ยน CalculateArea,​ CalculateVolume ไปเป็น Getter แทน \\ \\
 +จะสังเกตว่า เมื่อเราเปลี่ยนค่า Radius หรือ Height ค่าของ Area, Volume ก็จะถูก Update ตามเสมอ เพราะอย่างเช่นที่เคยอธิบายข้างบนไว้แล้วว่า Getter จะถูกเรียกทุกครั้ง ที่ Property ตัวนั้นถูกเรียกให้แสดงค่า ซึ่งในกรณีนี้ ถูกเรียกให้แสดงค่าใน ShowData นั่นเอง
 + 
 +<sxh delphi;​highlight:​ []>
 +program Cylinder_With_Properties;​
 +
 +type
 +
 +  { TMyCylinder }
 +
 +  TMyCylinder = Object
 +  private
 +    function GetRadius: real;
 +    function GetVolume: real;
 +  public
 +    Radius:​real; ​  //​Input
 +    Height:​real; ​  //​Input
 +    property Area:real read GetRadius; ​   //Output
 +    property Volume:real read GetVolume; ​ //Output
 +    procedure ShowData;
 +  end;
 +
 +{ TMyCylinder }
 +
 +function TMyCylinder.GetRadius:​ real;
 +begin
 +  result:​=system.pi*(Radius*Radius);​
 +end;
 +
 +function TMyCylinder.GetVolume:​ real;
 +begin
 +  result:​=Area*Height;​
 +end;
 +
 +procedure TMyCylinder.ShowData;​
 +begin
 +  writeln('​Radius = ',​Radius);​
 +  writeln('​Area = ',​Area);​
 +  writeln('​Volume = ',​Volume);​
 +end;
 +
 +var
 +  Cylinder:​TMyCylinder;​
 +
 +begin
 +  Cylinder.Radius:​=2;​ //Set Radius = 2
 +  Cylinder.Height:​=10;​ //Set Height = 10
 +  Cylinder.ShowData; ​ //Show the results
 +
 +  Cylinder.Radius:​=10;​ //Change Radius to 10
 +  Cylinder.ShowData; ​ //Show the results
 +
 +  Cylinder.Radius:​=5;​ //Change Radius to 5
 +  Cylinder.Height:​=2;​ //Change Height = 2
 +  Cylinder.ShowData; ​ //Show the results
 +
 +  readln;
 +end.  ​
 +</​sxh> ​
 +Compiled Results:
 +</​hidden>​
 +\\ 
  
  
  
tutorial/record.1547125317.txt.gz · Last modified: 2019/01/10 20:01 by admin