OOP in Delphi Arabic
OOP in Delphi Arabic
OOP in Delphi Arabic
اﻟﺒﻮﺻﻠﺔ اﻟﺘﻘﻨﻴﺔ
www.boosla.com
ﺍﻟﻔﺼﻞ ﺍﻷﻭﻝ
OOP in Delphi
ﺍﻟﱪﳎﺔ ﻏﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟـﻪ ﰲ ﺩﻟﻔﻲ
ﺍﻟﻔﻬﺮﺱ ..
٣ ﻣﻘﺪﻣﺔ ...............................................................................................
اﻟﻤﺰﻳﺪ ﻋﻦ اﻟﺘﻐﻠﯿﻒ
٢٢ اﻟﺘﻐﻠﯿﻒ ﻣﻊ اﻷﺷﻜﺎل .........................................................................
٢
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﺗﻌﺘﻤﺪ "ﺑﻴﺌﺔ ﺍﻟﺘﻄﻮﻳﺮ ﺩﻟﻔﻲ" ﻋﻠﻰ ﺍﻟﱪﳎﺔ ﻏﺮﺿﻴﺔ ﺍﻟﺘﻮﺟﻪ .ﺩﻟﻔﻲ ﻫﻲ ﺗﻮﺳﻴﻊ ﻟﻠﻐﺔ ﺍﻟﱪﳎﺔ ﺑﺎﺳﻜﺎﻝ ،ﻭﺍﻟﱵ ﻋﺮﻓﺖ ﺑﺈﺳﻢ
ﺑﺎﺳﻜﺎﻝ ﺍﻟﻐﺮﺿﻴﺔ ). (Object Pascal
ﻋﺰﻣﺖ ﺑﻮﺭﻻﻧﺪ ﻋﻠﻰ ﺍﻹﺷﺎﺭﺓ ﻟﻠﻐﺔ ﺑﺎﻹﺳﻢ )"ﺍﻟﻠﻐﺔ ﺩﻟﻔﻲ"( ﺃﻭ )" ("The Delphi languageﻭﺇﻋﺘﺒﺎﺭﻫﺎ ﻟﻐﺔ ﻣﺴﺘﻘﻠﺔ ﺑﺪﻻ ﻣﻦ
ﺗﺴﻤﻴﺘﻬﺎ ﺑﻴﺌﺔ ﺍﻟﺘﻄﻮﻳﺮ ﺩﻟﻔﻲ )" . ("Delphi development environment
ﺭﲟﺎ ﻳﻜﻮﻥ ﺫﻟﻚ ﻹﻥ ﺑﻮﺭﻻﻧﺪ ﺗﺮﻳﺪ ﺃﻥ ﺗﺼﺒﺢ ﻗﺎﺩﺭﺓ ﻋﻠﻰ ﺍﻟﻘﻮﻝ ﺑﺈﻥ ﻛﻴﻠﻜﺲ ) (Kylixﺗﺴﺘﺨﺪﻡ ﺍﻟﻠﻐﺔ ﺩﻟﻔﻲ ،ﻛﻤﺎ ﺃﺎ
ﻭﻓﺮﺕ ﺩﻟﻔﻲ ﻟﻠﻌﻤﻞ ﲢﺖ ﻣﻨﺼﺔ ﻣﺎﻳﻜﺮﻭﺳﻮﻓﺖ ﺩﻭﺕ_ﻧﻴﺖ ) ، (Microsoft .NET platformﻭﺭﲟﺎ ﻳﺴﻌﻨﺎ ﺍﻟﻘﻮﻝ ﺃﻥ ﺩﻟﻔﻲ
ﻣﻌﺮﻭﻓﺔ ﻛﻠﻐﺔ ﺑﺮﳎﺔ ﻣﺴﺘﻘﻠﺔ ﰲ ﺻﻒ ﺍﻟﻠﻐﺎﺕ ﺍﻷﻛﺜﺮ ﺷﻴﻮﻋﺎ ﰲ ﺍﻟﻌﺎﱂ ﻭﻟﻴﺴﺖ ﳎﺮﺩ ﺑﻴﺌﺔ ﺗﻄﻮﻳﺮ ﺗﻌﺘﻤﺪ ﺑﺎﺳﻜﺎﻝ ﺍﻟﻐﺮﺿﻴﺔ .
ﻋﻠﻰ ﻛﻞ ﺣﺎﻝ ﺳﻮﺍﺀ ﻛﺎﻧﺖ "ﺑﻴﺌﺔ ﺍﻟﺘﻄﻮﻳﺮ ﺩﻟﻔﻲ " ﺃﻭ "ﺍﻟﻠﻐﺔ ﺩﻟﻔﻲ" ،ﻓﺈﻥ ﺍﻟﺮﻭﺡ ﻫﻲ ﻧﻔﺴﻬﺎ ﻟﻐﺔ ﺑﺮﳎﺔ ﻗﻮﻳﺔ ﻭﻣﺴﺘﻘﺮﺓ ﲤﻴﺰﻫﺎ
ﺇﻧﺘﺎﺟﻴﺘﻬﺎ ﺍﻟﻔﺮﻳﺪﺓ .
ﻻ ﺃﻇﻦ ﺃﱐ ﺳﺄﻗﻒ ﻃﻮﻳﻼ ﺃﻣﺎﻡ ﻫﺬﺍ ﺍﳌﻮﺿﻮﻉ ﻭﺳﺄﺳﺘﺨﺪﻡ ﺍﻟﺘﺴﻤﻴﺔ ﺍﻟﱵ ﲣﺮﺝ ﻣﻌﻲ ﺃﻭﻻﹰ .
،ﺣﱴ ﺃﻥ ﻣﻘﺪﺍﺭ object-oriented programming ﺇﻥ ﻣﻌﻈﻢ ﺍﻟﻠﻐﺎﺕ ﺍﳊﺪﻳﺜﺔ ﺗﺪﻋﻢ ﺍﻟﱪﳎﺔ ﻏﺮﺿﻴﺔ ﺍﻟﺘﻮﺟﺔ ) (OOPﺃﻭ
ﺩﻋﻢ ﺍﻟﻠﻐﺔ ﻟﻠـ OOPﺃﺻﺒﺢ ﻳﻨﻈﺮ ﺇﻟﻴﺔ ﰲ ﻛﺜﲑ ﻣﻦ ﺍﻷﺣﻴﺎﻥ ﻛﻤﻘﻴﺎﺱ ﻳﻌﱪ ﻋﻦ ﺃﳘﻴﺔ ﺍﻟﻠﻐﺔ .
ﺗﻌﺘﻤﺪ ﺍﻟﱪﳎﺔ ﻏﺮﺿﻴﺔ ﺍﻟﺘﻮﺟﺔ ﻋﻠﻰ ﺛﻼﺙ ﻣﻔﺎﻫﻴﻢ ﺃﺳﺎﺳﻴﺔ ﺳﻨﻌﺎﳉﻬﺎ ﰲ ﻫﺬﺍ ﺍﻟﻔﺼﻞ :
-ﺍﻟﺘﻐﻠﻴﻒ . encapsulation
. -ﺍﻟﻮﺭﺍﺛﺔ
inheritance
-ﺗﻌﺪﺩﻳﺔ ﺍﻷﺷﻜﺎﻝ . polymorphism
ﺩﻟﻔﻲ ﻫﻲ ﺗﻮﺳﻴﻊ ﻏﺮﺿﻲ_ﺍﻟﺘﻮﺟﺔ ﻟﻠﻐﺔ ﺑﺎﺳﻜﺎﻝ ﺍﻟﺘﻘﻠﻴﺪﻳﺔ .ﻭﻣﺎ ﺃﺭﻳﺪ ﺍﻟﺘﻨﻮﻳﺔ ﺇﻟﻴﺔ ﻫﻨﺎ ﺃﻥ ﺍﻟﺼﻴﺎﻏﺔ ﺍﻟﻨﺤﻮﻳﺔ ﻟﻠﻐﺔ ﺍﻟﺒﺎﺳﻜﺎﻝ
ﻣﺸﻬﻮﺭﺓ ﺑﺈﺎ ﺻﻴﺎﻏﺔ ﺃﻛﺜﺮ ﻭﺿﻮﺣﺎ ﻭﻗﺎﺑﻠﻴﺔ ﻟﻠﻘﺮﺍﺀﺓ ﻣﻦ ﻣﻌﻈﻢ ﺍﻟﻠﻐﺎﺕ ﺍﻷﺧﺮﻯ )ﻭﻟﻨﻘﻞ ﻣﺜﻼ ﻟﻐﺔ ، ( Cﻭﺑﺎﻟﺘﺎﱄ ﻛﻤﻴﺔ ﺃﻛﱪ
ﻣﻦ ﺍﳊﺸﻮ ﻣﻦ ﺃﺟﻞ ﺍﳊﺼﻮﻝ ﻋﻠﻰ ﺷﻔﺮﺓ ﻣﻘﺮﻭﺀﺓ ﺗﺸﺒﺔ ﺍﻟﻜﻼﻡ ﺍﻟﻌﺎﺩﻱ ﲝﻴﺚ ﳝﻜﻦ ﻓﻬﻤﻬﺎ ﻭﺗﺬﻛﺮﻫﺎ ﺑﺸﻜﻞ ﺳﺮﻳﻊ ﻭﻣﻨﺘﻈﻢ
ﻭﻫﺬﺍ ﳑﺎ ﻳﻘﻞ ﻣﻦ ﺍﻟﻮﻗﻮﻉ ﺑﺎﻷﺧﻄﺎﺀ .
ﻛﻤﺎ ﺃﻥ ﺍﻟﺘﻮﺳﻊ ﺍﻟﻐﺮﺿﻲ_ﺍﻟﺘﻮﺣﻪ ﳍﺬﺓ ﺍﻟﻐﺔ ﺑﺈﻋﺘﺮﺍﻑ ﺍﳉﻤﻴﻊ ﻻ ﻳﻘﻞ ﺃﳘﻴﺔ ﻋﻦ ﺍﳌﻮﺟﻮﺩ ﰲ ﺍﻟﻨﺴﻞ ﺍﳊﺎﱄ ﻟﻠﻐﺎﺕ ﺍﻟﱪﳎﺔ
ﺍﻟﻐﺮﺿﻴﺔ ﻣﻦ Javaﺣﱴ . C#
٣
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﻭﻣﻦ ﺍﳌﻬﻢ ﺃﻥ ﺗﻔﻬﻢ ﺃﻥ ﻛﻞ ﻣﻜﻮﻥ ﰎ ﻭﺿﻌﺔ ﻋﻠﻰ ﺍﻟﺸﻜﻞ ﻫﻮ ﻋﺒﺎﺭﺓ ﻏﺮﺽ ،ﻭﻫﺬﺍ ﺍﻟﻐﺮﺽ ﺧﺎﺹ ﺑﺼﻨﻒ ﻣﻌﲔ ...
ﺗﻮﺿﻴﺢ :
ﺍﳌﺼﻄﻠﺤﺎﻥ ﻏﺮﺽ ﻭﺻﻨﻒ ﻳﺴﺘﺨﺪﻣﺎﻥ ﺑﻜﺜﺮﺓ ،ﻭﻛﺜﲑﺍ ﻣﺎ ﻳﺘﻢ ﺇﺳﺎﺀﺓ ﻓﻬﻤﻬﻤﺎ ،ﺃﻛﺎﺩﳝﻴﺎ ﻧﺴﺘﻄﻴﻊ ﺍﻟﻘﻮﻝ ﺃﻥ :
ﺍﻟﺼﻨﻒ :ﻫﻮ ﳕﻂ ﻣﻌﻄﻴﺎﺕ ﻣﻌﺮﻑ ﳝﻠﻚ ﺑﻌﺾ ﺍﻟﺘﻮﺻﻴﻔﺎﺕ ،ﻭﺑﻌﺾ ﺍﻟﻌﻤﻠﻴﺎﺕ " ﺍﻟﺘﺼﺮﻓﺎﺕ" )ﺃﻭ ﻣﺎ ﻳﺴﻤﻰ ﻣﻨﺎﻫﺞ( .
ﺍﻟﻐﺮﺽ :ﻫﻮ ﻣﻨﺘﺴﺦ ﻣﻦ ﺍﻟﺼﻨﻒ ) ،ﺃﻭ ﻣﺘﻐﲑ ﻣﻦ ﳕﻂ ﻣﻌﻄﻴﺎﺕ ﺻﻨﻒ ( .ﲝﻴﺚ ﳝﻠﻚ ﻗﻴﻢ ﻟﻜﻞ ﺍﻟﺘﻮﺻﻴﻔﺎﺕ ﺍﻟﱵ ﳛﺪﺩﻫﺎ
ﺍﻟﺼﻨﻒ ،ﻭﳝﻜﻨﺔ ﺇﺳﺘﻌﻤﺎﻝ ﻋﻤﻠﻴﺎﺗﻪ ﻭﳜﻀﻊ ﻟﺘﺼﺮﻓﺎﺗﺔ ﻭﺧﻮﺍﺻﺔ ..،
٤
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﺍﻟﻌﻼﻗﺔ ﺑﲔ ﺍﻟﻐﺮﺽ ) (objectﻭ ﺍﻟﺼﻨﻒ) (classﻫﻲ ﻧﻔﺴﻬﺎ ﺍﻟﻌﻼﻗﺔ ﺑﲔ ﺍﳌﺘﺤﻮﻝ) (variableﻭﺍﻟﻨﻤﻂ ). (type
ﺇﻥ ﻣﺘﺤﻮﻝ ﻣﻦ ﳕﻂ ﺻﻨﻒ ﻣﻌﲔ ﰲ ﺩﻟﻔﻲ ﻛﻤﺎ ﻫﻮ ﺍﳊﺎﻝ ﰲ ﻣﻌﻈﻢ ﻟﻐﺎﺕ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴﺔ ﺍﻟﺘﻮﺟﺔ ﻟﻦ ﳝﺜﻞ ﲣﺰﻳﻨﺎ ﻟﻠﻐﺮﺽ ﰲ
ﺍﻟﺬﺍﻛﺮﺓ ﺿﻤﻦ ﻫﺬﺍ ﺍﳌﺘﺤﻮﻝ ،ﻭﻟﻜﻨﺔ ﻓﻘﻂ ﻋﺒﺎﺭﺓ ﻋﻦ ﻣﺆﺷﺮ ﺇﱃ ﺍﻟﻐﺮﺽ ﰲ ﺍﻟﺬﺍﻛﺮﺓ .
ﻭﺑﻨﺎﺀ ﻋﻠﻰ ﺫﻟﻚ ﻓﺈﻧﻨﺎ ﻻ ﻧﺴﺘﻄﻴﻊ ﺍﻟﺘﻌﺎﻣﻞ ﻣﺒﺎﺷﺮﺓ ﻣﻊ ﺍﻷﻏﺮﺍﺽ ﻛﻤﺎ ﻧﺘﻌﺎﻣﻞ ﻣﻊ ﺍﳌﺘﺤﻮﻻﺕ ﺍﻟﻌﺎﺩﻳﺔ ،ﻹﻥ ﺍﻷﻏﺮﺍﺽ ﻟﻦ ﲣﺰﻥ
ﰲ ﺫﺍﻛﺮﺓ ﺍﳌﺘﺤﻮﻝ ﺍﳌﻌﺮﻑ ﳍﺎ ﻛﻤﺎ ﳛﺪﺙ ﰲ ﺣﺎﻟﺔ ﻣﺘﺤﻮﻝ ﻋﺎﺩﻱ ،ﺑﻞ ﻫﻲ ﲝﺎﺟﺔ ﺇﱃ ﺣﺠﺰ ﻳﺪﻭﻱ ﳌﺴﺎﺣﺔ ﺫﺍﻛﺮﺓ ﺧﺎﺻﺔ
ﺎ ﻭﻣﻦ ﰒ ﻳﺼﺒﺢ ﺍﳌﺘﺤﻮﻝ ﺍﳋﺎﺹ ﺎ ﻳﺆﺷﺮ ﻋﻠﻰ ﻫﺬﺓ ﺍﳌﺴﺎﺣﺔ ،ﺃﻱ ﳜﺰﻥ ﻋﻨﻮﺍﻥ ﻫﺬﺓ ﺍﳌﺴﺎﺣﺔ ﻓﻘﻂ ،ﻭﻻﳜﺰﻥ ﺑﻴﺎﻧﺎﺕ
ﺍﻟﻐﺮﺽ ﺿﻤﻨﺔ..
ﺇﺫﻥ ﻭﺟﺪﻧﺎ ﺍﻵﻥ ﻓﺮﻗﺎ ﻣﻬﻤﺎ ﺑﲔ ﻃﺮﻳﻘﺔ ﺍﻟﺘﻌﺎﻣﻞ ﻣﻊ ﺍﳌﺘﺤﻮﻻﺕ ﺍﻟﻌﺎﺩﻳﺔ ﻭﻣﻊ ﺍﻷﻏﺮﺍﺽ ،ﻭﻗﻠﻨﺎ ﺃﻧﺔ ﳚﺐ ﺣﺠﺰ )ﺇﻧﺸﺎﺀ( ﺫﺍﻛﺮﺓ
ﻟﻠﻐﺮﺽ ﻗﺒﻞ ﺇﺳﺘﺨﺪﺍﻣﺔ ،،،ﻛﻴﻒ ﻳﺘﻢ ﺫﻟﻚ ؟
-١ﺇﻧﺸﺎﺀ ﻭﺣﺠﺰ ﺍﻟﺬﺍﻛﺮﺓ ﻳﺪﻭﻳﺎ ﻟﻐﺮﺽ ﻣﻦ ﺻﻨﻒ ﻣﺎ ) ..ﺑﺈﺳﺘﺨﺪﺍﻡ ﺍﳌﻨﻬﺞ ﺍﻟﺒﺎﱐ (Create
-٢ﺃﻭ ﻧﺴﺐ ﺍﻟﻐﺮﺽ ﺇﱃ ﻏﺮﺽ ﻣﻮﺟﻮﺩ ﰎ ﺣﺠﺰ ﺍﻟﺬﺍﻛﺮﺓ ﻟﻪ ﻣﺴﺒﻘﺎ ) ..ﺑﺈﺳﺘﺨﺪﺍﻡ ﺍﻟﻨﺴﺐ =( :
var
;Obj1, Obj2: TClass
begin
// assign a newly created object
;Obj1 := TMyClass.Create
// assign to an existing object
;Obj2 := Obj1
٥
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﰲ ﻫﺬﺍ ﺍﳌﺜﺎﻝ ﻗﻤﻨﺎ ﺑﺘﻌﺮﻳﻒ ﻏﺮﺿﲔ Obj1, Obj2ﻣﻦ ﺍﻟﺼﻨﻒ ، Tclassﺍﻟﻐﺮﺽ ﺍﻷﻭﻝ obj1ﻗﻤﻨﺎ ﺑﺈﻧﺸﺎﺀﺓ ﺑﺎﻟﻄﺮﻳﻘﺔ
ﺍﻷﻭﱃ ﺑﺈﺳﺘﺨﺪﺍﻡ ﺍﳌﻨﻬﺞ ﺍﳌﻬﻢ ﻭﺍﻟﺸﺎﺋﻊ Createﺍﻟﺬﻱ ﳛﺠﺰ ﺍﻟﺬﺍﻛﺮﺓ ﻟﺔ ﻭﻳﻬﻴﺌﺔ ﻟﻺﺳﺘﺨﺪﺍﻡ .ﻭﺍﻟﻐﺮﺽ ﺍﻟﺜﺎﱐ obj2ﻗﻤﻨﺎ
ﺑﻨﺴﺒﺔ ﺇﱃ ﻏﺮﺽ ﻣﻮﺟﻮﺩ ﻣﺴﺒﻘﺎ ﻭﻫﻮ ، Obj1ﻭﻛﻼ ﺍﻟﻄﺮﻳﻘﺘﲔ ﺻﺤﻴﺤﺘﲔ ﻭﻣﺴﺘﺨﺪﻣﺘﲔ .
ﻣﻬﻢ :ﲟﺎ ﺃﻧﻨﺎ ﻗﻤﻨﺎ ﲝﺠﺰ ﺍﻟﺬﺍﻛﺮﺓ ﻳﺪﻭﻳﺎ ﺑﺈﺳﺘﺨﺪﺍﻡ ﺍﳌﻨﻬﺞ ، Createﻓﺈﻧﺔ ﻳﺘﻮﺟﺐ ﻋﻠﻴﻨﺎ ﲢﺮﻳﺮﻫﺎ ﻳﺪﻭﻳﺎ ﺃﻳﻀﺎﹰ ،ﻭﻳﺘﻢ ﺫﻟﻚ
ﺑﺈﺳﺘﺨﺪﺍﻡ ﺍﳌﻨﻬﺞ . Freeﺳﻨﻠﻘﻲ ﻧﻈﺮﺓ ﺗﻔﺼﻴﻠﻴﺔ ﻋﻠﻰ ﻫﺬﻳﻦ ﺍﳌﻨﻬﺠﲔ ﰲ ﻫﺬﺍ ﺍﻟﺒﺤﺚ .
(Finaly ....ﻟﺘﻌﺮﻳﻒ ﺍﻷﺻﻨﺎﻑ ﻭﲢﺮﻳﺮﻫﺎ ، )Try ﺃﻧﺼﺤﻚ ﺑﺈﺳﺘﺨﺪﺍﻡ ﻣﻌﺎﳉﺔ ﺍﻹﺳﺘﺜﻨﺎﺀﺍﺕ
ﻛﺬﻟﻚ ﻓﺈﻥ ﻣﻌﺎﳉﺔ ﺍﻹﺳﺘﺜﻨﺎﺀﺍﺕ ﺳﻨﺘﺤﺪﺙ ﻋﻨﻬﺎ ﻻﺣﻘﺎ ،ﺇﻥ ﱂ ﻳﻜﻦ ﻟﺪﻳﻚ ﺗﺼﻮﺭ ﻭﺍﺿﺢ ﻋﻨﻬﺎ ﺑﻌﺪ .
ﻟﺘﻌﺮﻳﻒ ﺻﻨﻒ ﺟﺪﻳﺪ ﰲ ﺩﻟﻔﻲ ،ﺩﻋﻨﺎ ﻧﺘﺬﻛﺮ ﺃﻥ ﺍﻟﺼﻨﻒ ﳛﻮﻱ ﺷﻴﺌﲔ ﻣﻬﻤﲔ ﳘﺎ ﺍﳊﻘﻮﻝ )ﺑﻴﺎﻧﺎﺕ ﺍﻟﺼﻨﻒ( ﻭﺍﳌﻨﺎﻫﺞ
)ﻋﻤﻠﻴﺎﺕ ﺍﻟﺼﻨﻒ( .
ﺇﺫﺍ ﻓﻜﺮﻧﺎ ﺑﻨﺎﺀً ﻋﻠﻰ ﻣﺎ ﺳﺒﻖ ﻣﺎﺫﺍ ﳓﺘﺎﺝ ﻟﻨﻌﺮﻑ ﺻﻨﻒ ﺟﺪﻳﺪ ،ﻟﻮﺟﺪﻧﺎ ﺃﻧﻨﺎ ﻧﺮﻳﺪ ﺗﻌﺮﻳﻒ ﺍﳊﻘﻮﻝ ﺍﻟﱵ ﳛﻮﻳﻬﺎ ﻫﺬﺍ ﺍﻟﺼﻨﻒ
ﻭﺍﻟﻌﻤﻠﻴﺎﺕ ﺍﻟﱵ ﻳﺴﺘﻄﻴﻊ ﺇﳒﺎﺯﻫﺎ ،ﻭﺑﺎﻟﺘﺄﻛﻴﺪ ﻧﻌﺮﻑ ﻟﻪ ﺇﲰﺎ ﻓﺮﻳﺪﺍ ﺧﺎﺹ ﺑﻪ .
ﺍﳊﻘﻮﻝ ﻫﻲ ﻋﺒﺎﺭﺓ ﻋﻦ ﻣﺘﺤﻮﻻﺕ ﻋﺎﺩﻳﺔ ،ﻭﺍﻟﻌﻤﻠﻴﺎﺕ ﻫﻲ ﻋﺒﺎﺭﺓ ﻋﻦ ﻣﻨﺎﻫﺞ )ﺃﻱ ﺗﻮﺍﺑﻊ ﺃﻭ ﺇﺟﺮﺍﺀﺍﺕ( .ﺗﻨﺴﻴﻖ ﻫﺬﺍ ﺍﻟﺘﻌﺮﻳﻒ
ﻳﺘﻢ ﺑﺼﻮﺭﺓ ﺑﺴﻴﻄﺔ – ﺑﺈﻥ ﻧﺬﻛﺮ ﰲ ﻗﺴﻢ Typeﺇﺳﻢ ﺍﻟﺼﻨﻒ ﳏﺪﺩﺍﹰ ﺑﺎﻟﻜﻠﻤﺔ ﺍﳌﻔﺘﺎﺣﻴﺔ Classﻭﻧﺘﺒﻌﻪ ﻣﺒﺎﺷﺮﺓ ﺑﺘﻌﺮﻳﻒ
ﺍﳊﻘﻮﻝ ﺍﳋﺎﺻﺔ ﺑﻪ ،ﰒ ﺭﺅﻭﺱ ﺍﳌﻨﺎﻫﺞ ﺍﻟﱵ ﻳﻌﺮﻓﻬﺎ ،ﻭﺑﺎﻟﺘﺄﻛﻴﺪ ﻧﻨﻬﻲ ﺫﻟﻚ ﺑـ ;: End
Type
TDate = class
;Month, Day, Year: Integer
;)procedure SetValue (m, d, y: Integer
ﳛﺪد إذا ﻛﺎﻧﺖ اﻟﺴﻨﺔ ﻛﺒﯿﺴﺔ function LeapYear: Boolean; //
;end
٦
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﻣﻼﺣﻈﺔ :
ﺇﻥ ﺍﻟﺒﺎﺩﺋﺔ Tﺍﻟﱵ ﺳﺒﻘﻨﺎ ﺎ ﺇﺳﻢ ﺍﳌﺘﺤﻮﻝ ﻫﻲ ﻋﺒﺎﺭﺓ ﻋﻦ ﺗﻘﻠﻴﺪ )ﻋﺮﻑ( ﻟﻠﻤﺘﺮﺟﻢ ،ﻳﺘﺒﻌﺔ ﻣﱪﳎﻮ ﺍﻟﺪﻟﻔﻲ ﻣﻨﺬ ﻇﻬﻮﺭﻫﺎ ﺑﺈﻳﻌﺎﺫ
ﻣﻦ ﺷﺮﻛﺔ ﺑﻮﺭﻻﻧﺪ ﻧﻔﺴﻬﺎ .ﺍﳊﺮﻑ Tﻫﻮ ﺇﺧﺘﺼﺎﺭ ﻟـ ، Typeﻭﻫﻮ ﳎﺮﺩ ﺣﺮﻑ ﻭﻟﻜﻦ ﺇﺗﺒﺎﻉ ﻫﺬﺍ ﺍﻟﻌﺮﻑ ﺳﻴﺠﻌﻞ
ﺷﻔﺮﺗﻚ ﻣﻔﻬﻮﻣﺔ ﺃﻛﺜﺮ ﻣﻦ ﻗﺒﻞ ﺑﻘﻴﺔ ﺍﳌﻄﻮﺭﻳﻦ ﺍﻟﺬﻳﻦ ﺍﻋﺘﺎﺩﻭ ﻋﻠﻰ ﺫﻟﻚ .
ﺭﲟﺎ ﻻﺣﻈﺖ ﻣﻦ ﺗﻌﺮﻳﻒ ﺍﻟﺼﻨﻒ ﺃﻧﻨﺎ ﻗﻤﻨﺎ ﺑﺘﻌﺮﻳﻒ ﺃﲰﺎﺀ ﺍﻟﺘﻮﺍﺑﻊ ﻭﺍﻹﺟﺮﺍﺀﺍﺕ ﻓﻘﻂ )ﺭﺅﻭﺱ ﺍﳌﻨﺎﻫﺞ( ﻭﱂ ﻧﻘﻢ ﺑﻜﺘﺎﺑﺔ
ﺃﺟﺴﺎﻣﻬﺎ ﻫﻨﺎﻙ ،ﺣﻴﺚ ﻧﻘﻮﻡ ﺑﺘﻌﺮﻳﻒ ﺃﺟﺴﺎﻡ ﺍﳌﻨﺎﻫﺞ )ﺗﻮﺍﺑﻊ+ﺇﺟﺮﺍﺀﺍﺕ( ﰲ ﺟﺴﻢ ﺍﻟﻮﺣﺪﺓ ﻧﻔﺴﻬﺎ ،ﺃﻱ ﻗﺴﻢ ﺍﻟـ
Implementationﺍﳋﺎﺹ ﺎ .
ﻭﲟﺎ ﺃﻧﻨﺎ ﻧﺴﺘﻄﻴﻊ ﺗﻌﺮﻳﻒ ﺃﻛﺜﺮ ﻣﻦ ﺻﻨﻒ ﰲ ﺍﻟﻮﺣﺪﺓ ) (Unitﻭﻟﻜﻞ ﺻﻨﻒ ﻣﻨﺎﻫﺞ ﺧﺎﺻﺔ ﺑﻪ ﻟﺬﻟﻚ ﳚﺐ ﲤﻴﻴﺰ ﺟﺴﻢ ﻛﻞ
ﻣﻨﻬﺞ ﻟﻨﻌﺮﻑ ﻹﻱ ﺻﻨﻒ ﻳﺘﺒﻊ .ﻣﻦ ﺃﺟﻞ ﺫﻟﻚ ﻓﺈﻥ ﺗﻌﺮﻳﻒ ﺃﺟﺴﺎﻡ ﺍﳌﻨﺎﻫﺞ ﻳﺴﺒﻖ ﺑﺈﺳﻢ ﺍﻟﺼﻨﻒ ﻣﻔﺼﻮﻻ ﺑﻨﻘﻄﺔ ﻋﻦ ﺇﺳﻢ
ﺍﳌﻨﻬﺞ ﻣﺜﻼ : TDate.SetValue
Implementation
…
ﻓﻜﺮﺓ :
ﺇﺫﺍ ﺿﻐﻄﺖ Ctrl+Shift+Cﻋﻨﺪﻣﺎ ﻳﻜﻮﻥ ﺍﳌﺆﺷﺮ ﺿﻤﻦ ﺗﻌﺮﻳﻒ ﺍﻟﺼﻨﻒ ،ﻓﺈﻥ ﻣﻴﺰﺓ ﺗﻜﻤﻴﻞ ﺍﻟﺘﻌﺮﻳﻒ ﰲ ﺩﻟﻔﻲ ﺳﻮﻑ ﺗﻘﻮﻡ
ﺗﻠﻘﺎﺋﻴﺎ ﲟﺴﺎﻋﺪﺗﻚ ﻭﺗﻮﻟﻴﺪ ﻫﻴﻜﻞ ﺍﻟﺘﻌﺮﻳﻒ ﺍﳋﺎﺹ ﺑﺎﳌﻨﺎﻫﺞ ﺍﻟﱵ ﻗﻤﺖ ﺑﺘﻌﺮﻳﻔﻬﺎ ﰲ ﺍﻟﺼﻨﻒ .
ﻋﺮﻓﻨﺎ ﺍﻵﻥ ﻛﻴﻒ ﻧﺒﲏ ﺻﻨﻒ ﺟﺪﻳﺪ ،ﻭﺃﻧﻨﺎ ﻧﺴﺘﻄﻴﻊ ﺃﻥ ﻧﻨﺸﻲﺀ ﺃﻏﺮﺍﺿﺎﹰ ﻣﻦ ﻫﺬﺍ ﺍﻟﺼﻨﻒ ﻭﺇﺳﺘﺨﺪﺍﻣﻬﺎ ﰲ ﺷﻔﺮﺗﻨﺎ .
٧
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
var
;ADay: TDate
begin
// create an object
;ADay := TDate.Create
try
// use the object
;)ADay.SetValue (1, 1, 2000
if ADay.LeapYear then
;))ShowMessage ('Leap year: ' + IntToStr (ADay.Year
finally
// destroy the object
;ADay.Free
;end
;end
ﻻﺣﻆ ﺃﻥ ﺍﻟﺘﻌﺒﲑ ADay.LeapYearﻣﺸﺎﺑﺔ ﲤﺎﻣﺎ ﻟﻠﺘﻌﺒﲑ . ADay.Yearﻣﻊ ﺃﻥ ﺇﺣﺪﺍﳘﺎ ﻫﻮ ﺗﺎﺑﻊ ﻟﻠﺘﻨﻔﻴﺬ ،ﻭﺍﻵﺧﺮ ﻫﻮ
ﻣﺘﺤﻮﻝ )ﻭﺻﻮﻝ ﺑﻴﺎﻧﺎﺕ ﻣﺒﺎﺷﺮ( ،ﺃﻱ ﻧﺼﻞ ﻟﺒﻴﺎﻧﺎﺕ ﺍﻟﻐﺮﺽ ﺑﻨﻔﺲ ﻃﺮﻳﻘﺔ ﺍﻟﻮﺻﻮﻝ ﳌﻨﺎﻫﺠﺔ ﻭﺫﻟﻚ ﺑﺈﺳﺘﺨﺪﺍﻡ ﺍﻟﻨﻘﻄﺔ .
-ﺑﺈﻣﻜﺎﻧﻚ ﺇﺧﺘﻴﺎﺭﻳﺎﹰ ﺃﻥ ﺗﻀﻴﻒ ﻗﻮﺳﺎﻥ ﻣﻐﻠﻘﺎﻥ ﺑﻌﺪ ﺇﺳﺘﺪﻋﺎﺀ ﺗﺎﺑﻊ ﻟﻴﺲ ﻟﺔ ﺑﺎﺭﺍﻣﺘﺮﺍﺕ ،ﻭﺑﺈﻣﻜﺎﻧﻚ ﲡﺎﻫﻠﻬﻤﺎ ﻋﻠﻰ ﻛﻞ ﺣﺎﻝ
ﺩﻟﻔﻲ ﺗﺪﻋﻢ ﺍﻟﺘﺤﻤﻴﻞ ﺍﻟﺰﺍﺋﺪ ﻟﻠﻤﻨﺎﻫﺞ )ﺍﻟﺘﻮﺍﺑﻊ +ﺍﻹﺟﺮﺍﺋﻴﺎﺕ( .ﻭﻟﻜﻦ ﻣﺎ ﻫﻮ ﺍﻟﺘﺤﻤﻴﻞ ﺍﻟﺰﺍﺋﺪ ﻳﺎﺗﺮﻯ ؟
ﺍﻟﺘﺤﻤﻴﻞ ﺍﻟﺰﺍﺋﺪ ﻳﻌﲏ ﺃﻥ ﻳﻜﻮﻥ ﻟﺪﻳﻚ ﻣﻨﻬﺠﺎﻥ ﺑﻨﻔﺲ ﺍﻹﺳﻢ ،ﺷﺮﻳﻄﺔ ﺃﻥ ﺗﻘﻮﻡ ﺑﺈﺿﺎﻓﺔ ﺍﻟﻜﻠﻤﺔ ﺍﳌﻔﺘﺎﺣﻴﺔ overloadingﺍﻟﻴﻬﻤﺎ
ﻭﺃﻥ ﺗﻜﻮﻥ ﻗﺎﺋﻤﺔ ﺍﻟﺒﺎﺭﺍﻣﺘﺮﺍﺕ )ﺍﳌﺘﻐﲑﺍﺕ( ﺍﳋﺎﺻﺔ ﻳﻜﻞ ﻣﻨﻬﻤﺎ ﳐﺘﻠﻔﺔ ﻋﻦ ﺍﻵﺧﺮ ) ،ﺇﺫﺍ ﺇﺗﻔﻘﺎ ﺑﺎﻹﺳﻢ ﻓﺈﻥ ﺩﻟﻔﻲ ﲝﺎﺟﺔ ﺇﱃ
ﺷﻲﺀ ﺁﺧﺮ ﻟﻠﺘﻤﻴﻴﺰ ﺑﻴﻨﻬﻤﺎ ﻟﺬﻟﻚ ﻓﺈﻥ ﻣﻨﻬﺠﲔ ﻣﺘﻔﻘﲔ ﺑﺎﻹﺳﻢ ﻭﺍﻟﺒﺎﺭﺍﻣﺘﺮﺍﺕ ﻻ ﳝﻜﻦ ﺃﻥ ﳓﺪﻳﺪ ﺃﻱ ﻣﻨﻬﻤﺎ ﻧﺮﻳﺪ ﺃﻥ ﻧﺴﺘﺨﺪﻡ (
.ﺑﻔﺤﺺ ﺍﻟﺒﺎﺭﺍﻣﺘﺮﺍﺕ ﻳﺴﺘﻄﻴﻊ ﻣﺘﺮﺟﻢ ﺍﻟﻠﻐﺔ ) (Compilerﲢﺪﻳﺪ ﺃﻱ ﻭﺍﺣﺪ ﻣﻨﻬﻤﺎ ﻧﺮﻳﺪ ﺃﻥ ﻧﺴﺘﺪﻋﻲ ،ﻭﻳﻘﻮﻡ ﺑﺎﻹﺳﺘﺪﻋﺎﺀ
ﺍﻟﺼﺤﻴﺢ ﻟﻠﻤﻨﻬﺞ ﺍﻟﺼﺤﻴﺢ .ﺳﻨﺮﻯ ﺗﻄﺒﻴﻘﺎﺕ ﻫﺬﺓ ﺍﳌﻴﺰﺓ ﻻﺣﻘﺎ
٨
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
-ﺍﻟﺘﻐﻠﻴﻒ
-ﺍﻟﻮﺭﺍﺛﺔ
-ﺗﻌﺪﺩﻳﺔ ﺍﻷﺷﻜﺎﻝ
ﺍﻟﺘﻐﻠﻴﻒ : Encapsulation
ﺗﻌﺘﻤﺪ ﻓﻜﺮﺓ ﻏﺮﺿﻴﺔ ﺍﻟﺘﻮﺟﺔ ﻋﻠﻰ ﺇﺧﻔﺎﺀ ﺍﻟﺒﻴﺎﻧﺎﺕ .ﻭﺗﺴﺘﺨﺪﻡ ﺍﻷﺻﻨﺎﻑ ﻟﺘﺤﻘﻴﻖ ﺫﻟﻚ .
ﻳﺘﻢ ﺇﺧﻔﺎﺀ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺩﺍﺧﻞ ﺍﻷﺻﻨﺎﻑ ﺍﳋﺎﺻﺔ ﺎ ،ﺃﻭ ﻧﻘﻮﻝ ﻳﺘﻢ ﺗﻐﻠﻴﻒ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺩﺍﺧﻞ ﺍﻷﺻﻨﺎﻑ .
ﻋﺎﺩﺓ ﻳﺘﻢ ﺗﻮﺿﻴﺢ ﻫﺬﺓ ﺍﻟﻔﻜﺮﺓ ﺑﺈﺳﺘﺨﺪﺍﻡ ﻣﺎ ﻳﺴﻤﻰ ﺍﻟﺼﻨﺎﺩﻳﻖ ﺍﻟﺴﻮﺩﺍﺀ ) ، (black boxesﺣﻴﺚ ﻻ ﺗﻀﻄﺮ ﺃﻥ ﺗﻌﺮﻑ
ﻛﻴﻒ ﺗﺘﻢ ﺍﻷﻣﻮﺭ ﺑﺎﻟﺪﺍﺧﻞ ﻭﻣﺎ ﻫﻲ ﺍﶈﺘﻮﻳﺎﺕ ﺍﻟﺪﺍﺧﻠﻴﺔ ،ﻭﻛﻞ ﻣﺎ ﻳﻬﻤﻚ ﻫﻮ ﻛﻴﻒ ﺗﺘﻌﺎﻣﻞ ﻣﻊ ﻭﺍﺟﻬﺔ ﺍﻟﺼﻨﺪﻭﻕ ﺍﻷﺳﻮﺩ
ﻭﺗﻌﻄﻴﺔ ﻣﻌﻄﻴﺎﺗﻚ ﻭﺗﺄﺧﺬ ﺍﻟﻨﺘﺎﺋﺞ ﺑﻐﺾ ﺍﻟﻨﻈﺮ ﻋﻦ ﻣﺎ ﻳﺘﻢ ﰲ ﺍﻟﺪﺍﺧﻞ .ﺇﻥ ﻣﺎ ﻳﻬﻤﻚ ﻓﻌﻠﻴﺎ ﻣﻦ ﺍﻟﺼﻨﺪﻭﻕ ﻫﻮ ﺁﻟﻴﺔ ﺍﻟﺘﻌﺎﻣﻞ
ﻣﻌﺔ )ﻣﻊ ﻭﺍﺟﻬﺘﺔ( ﻭﻻ ﺗﻌﻄﻲ ﺇﻫﺘﻤﺎﻣﺎ ﻛﺒﲑﺍ ﻋﻦ ﺗﻔﺎﺻﻴﻞ ﺩﺍﺧﻞ ﺍﻟﺼﻨﺪﻭﻕ ،ﻣﺜﻼ ﻳﻬﻤﻚ ﺃﻥ ﺗﺘﻔﺮﺝ ﻋﻠﻰ ﺍﻟﱪﺍﻣﺞ ﺍﳌﻔﻀﻠﻪ
ﻋﻠﻰ ﺍﻟﺘﻠﻔﺰﻳﻮﻥ ﻭﺃﻥ ﺗﻌﺮﻑ ﺗﻐﻴﲑ ﺍﶈﻄﺎﺕ ﻭﺇﻃﻔﺎﺀﺓ ﻭﺗﺸﻐﻴﻠﺔ ،ﺑﻐﺾ ﺍﻟﻨﻈﺮ ﻋﻦ ﻓﻬﻢ ﺍﻟﺪﺍﺭﺍﺕ ﺍﻟﺪﺍﺧﻠﻴﺔ ﺍﳌﻜﻮﻧﺔ ﻟﻠﺘﻠﻔﺰﻳﻮﻥ
..
ﺇﺫﻥ ﳔﺰﻥ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺩﺍﺧﻞ ﺍﻷﺻﻨﺎﻑ ﻭﻋﻨﺪﻫﺎ ﳝﻜﻨﻨﺎ ﺃﻥ ﻧﻜﺘﻔﻲ ﲟﻌﺮﻓﺔ ﻛﻴﻔﻴﺔ ﺇﺳﺘﺨﺪﺍﻣﻬﺎ ﻣﻦ ﺍﳋﺎﺭﺝ .ﺇﻥ ﻛﻴﻔﻴﺔ
ﺍﻹﺳﺘﺨﺪﺍﻡ ﺗﺪﻋﻰ ﻭﺍﺟﻬﺔ ﺍﻟﺼﻨﻒ ) (class interfaceﻭﻫﻲ ﺍﻟﱵ ﺗﺴﻤﺢ ﻟﻸﺟﺰﺍﺀ ﺍﻷﺧﺮﻯ ﻣﻦ ﺍﻟﱪﻧﺎﻣﺞ ﺑﺈﺳﺘﺨﺪﺍﻡ
ﺍﻷﻏﺮﺍﺽ ﺍﳌﻌﺮﻓﺔ ﻣﻦ ﻫﺬﺍ ﺍﻟﺼﻨﻒ ،ﻭﺑﺎﻟﺘﺎﱄ ﻋﻨﺪﻣﺎ ﺗﺴﺘﺨﺪﻡ ﻏﺮﺽ ﻣﺎ ﻓﺈﻥ ﻣﻌﻈﻢ ﺷﻔﺮﺗﻪ ﺗﻜﻮﻥ ﳐﻔﻴﺔ ،ﻭﻧﺎﺩﺭﺍ ﻣﺎ ﺗﻌﺮﻑ
ﻣﺎ ﻫﻲ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺍﻟﺪﺍﺧﻠﻴﻪ ﻟﻪ ﺣﱴ ﺃﻧﻪ ﻗﺪ ﻻ ﺗﻮﺟﺪ ﻃﺮﻳﻘﺔ ﻟﺪﺧﻮﻝ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺍﳋﺎﺻﺔ ﺑﻪ ﺑﺸﻜﻞ ﻣﺒﺎﺷﺮ ﻣﺎﱂ ﺗﺴﺘﺨﺪﻡ ﺍﳌﻨﺎﻫﺞ
ﺍﳌﺘﺎﺣﺔ ﻋﻠﻰ ﺍﻟﻮﺍﺟﻬﺔ ﻭﺍﻟﱵ ﺗﺴﻤﺢ ﻟﻚ ﺑﺘﻐﻴﲑ ﻭﻗﺮﺍﺀﺓ ﺍﻟﺒﻴﺎﻧﺎﺕ ،ﻭﺫﻟﻚ ﻳﻌﺘﱪ ﻣﻦ ﺃﻫﻢ ﺍﻟﻔﺮﻭﻕ ﺑﲔ ﺍﻟﱪﳎﺔ ﻏﺮﺿﻴﺔ ﺍﻟﺘﻮﺟﺔ
ﻭ ﺍﻟﱪﳎﺔ ﺍﻟﻜﻼﺳﻴﻜﻴﺔ ﻭﺍﻟﱵ ﺗﻜﻮﻥ ﺍﻟﺒﻴﺎﻧﺎﺕ ﻓﻴﻬﺎ ﻋﺎﻣﺔ ﻟﻜﻞ ﺍﻷﺻﻨﺎﻑ ﻏﲑ ﺗﺎﺑﻌﺔ ﻟﺼﻨﻒ ﳏﺪﺩ ﻛﻤﺎ ﺃﻧﻚ ﺗﺴﺘﻄﻴﻊ ﺗﻐﲑﻫﺎ
ﻣﺒﺎﺷﺮﺓ ﻭﺑﺎﻟﺘﺎﱄ ﺗﻘﻊ ﰲ ﻣﻄﺐ ﻋﺪﻡ ﺻﻼﺣﻴﺔ ﺍﻟﻘﻴﻤﺔ ﳊﺎﻟﺔ ﺃﻭ ﻤﻮﻋﺔ ﺣﺎﻻﺕ ...،،
٩
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
-ﻟﻮ ﻛﻨﺎ ﻧﺘﺒﻊ ﺍﻟﻄﺮﻳﻘﺔ ﺍﻟﻜﻼﺳﻴﻜﻴﺔ ﺑﺎﻟﱪﳎﺔ ﻓﺈﻥ ﺍﳌﺘﺤﻮﻻﺕ )ﺍﻟﺒﻴﺎﻧﺎﺕ( ﺳﺘﻜﻮﻥ ﻣﺘﺎﺣﺔ ﻟﻠﺪﺧﻮﻝ ﻭﺍﻟﺘﻐﻴﲑ ﺍﳌﺒﺎﺷﺮ ،
ﻭﺑﺎﻟﺘﺎﱄ ﻣﻦ ﺍﳌﻤﻜﻦ ﺇﺩﺧﺎﻝ ﻗﻴﻢ ﻏﲑ ﺻﺎﳊﺔ ﺑﺪﻭﻥ ﻭﺟﻮﺩ ﺇﻣﻜﺎﻧﻴﺔ ﻟﻠﺘﺄﻛﺪ ﻣﻨﻬﺎ ،ﻣﺜﻼ ﻟﻮ ﻗﻤﺖ ﺑﺈﺩﺧﺎﻝ ﺍﻟﺘﺎﺭﻳﺦ
٣٠) February 30ﺷﺒﺎﻁ( ﻭﺍﻟﺬﻱ ﻫﻮ ﺗﺎﺭﻳﺦ ﺧﺎﻃﻲﺀ ﻹﻥ ﺷﺒﺎﻁ ﻻﳛﻮﻱ ٣٠ﻳﻮﻡ ﻓﺈﻥ ﺍﻟﱪﻧﺎﻣﺞ ﺳﻴﻘﺒﻠﺔ ﻹﻧﻨﺎ ﻋﺮﻓﻨﺎ
ﻣﺘﺤﻮﻝ ﺍﻟﻴﻮﻡ ﻣﻦ ﺍﻟﻨﻮﻉ ﺍﻟﺼﺤﻴﺢ ) (Integerﺍﻟﺬﻱ ﻳﻘﺒﻞ ﻫﺬﺓ ﺍﻟﻘﻴﻤﺔ ،ﻭﺳﺘﺤﺼﻞ ﺍﻷﺧﻄﺎﺀ ﻻﺣﻘﺎ ﻋﻨﺪ ﺍﻟﻌﻤﻠﻴﺎﺕ
ﺍﳊﺴﺎﺑﻴﺔ ،ﺃﻭ ﺗﻌﻄﻲ ﻧﺘﺎﺋﺞ ﺧﺎﻃﺌﺔ ﲤﺎﻣﺎ .
-ﺃﻣﺎ ﰲ ﺣﺎﻝ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴﺔ ،ﻓﺈﻥ ﺍﻟﺪﺧﻮﻝ ﺍﳌﺒﺎﺷﺮ ﻟﻠﺒﻴﺎﻧﺎﺕ ﻏﲑ ﻣﺴﻤﻮﺡ ﻹﻥ ﺍﻟﺒﻴﺎﻧﺎﺕ ﻣﻐﻠﻔﺔ )ﳐﺒﺄﺓ ( ﰲ ﺍﻟﺼﻨﻒ
ﻭﺍﻟﻮﺻﻮﻝ ﺇﻟﻴﻬﺎ ﻳﺘﻢ ﺑﺈﺳﺘﺨﺪﺍﻡ ﺍﳌﻨﺎﻫﺞ ﺍﻟﱵ ﺧﺼﺼﻬﺎ ﺍﻟﺼﻨﻒ ﻟﺬﻟﻚ ،ﺃﻱ ﺃﻧﻚ ﻟﻦ ﺗﺴﺘﺨﺪﻡ ﺍﳌﺘﺤﻮﻝ ﻣﺒﺎﺷﺮﺓ ﺑﻞ
ﺳﺘﺘﻌﺎﻣﻞ ﻣﻊ ﺇﺟﺮﺍﺋﻴﺔ ﺃﻭ ﺗﺎﺑﻊ ﻹﺩﺧﺎﻝ ﺍﻟﻘﻴﻤﺔ ،ﻭﺑﺎﻟﺘﺎﱄ ﻟﻦ ﻳﻈﻬﺮ ﻣﻌﻨﺎ ﺍﻟﻨﻮﻉ ﺍﻟﺴﺎﺑﻖ ﻣﻦ ﺍﻷﺧﻄﺎﺀ ﻹﻥ ﻫﺬﺓ ﺍﳌﻨﺎﻫﺞ
ﳝﻜﻦ ﺑﺴﻬﻮﻟﺔ ﺗﻀﻤﻴﻨﻬﺎ ﺷﻔﺮﺍﺕ ﻟﻔﺤﺺ ﺍﻟﻘﻴﻢ ﻭﺍﻟﺘﺄﻛﺪ ﻣﻨﻬﺎ ،ﻭﺭﻓﺾ ﺍﻟﺘﻌﺪﻳﻼﺕ ﰲ ﺣﺎﻝ ﻛﺎﻧﺖ ﺍﻟﻘﻴﻤﺔ ﻏﲑ ﺻﺎﳊﺔ
.ﻻﺣﻆ ﺃﻧﻨﺎ ﺃﺳﺘﺨﺪﻣﻨﺎ ﺍﳌﻨﻬﺞ SetValueﻟﻀﺒﻂ ﺍﻟﻘﻴﻢ ﻭﱂ ﻧﻘﻢ ﺑﺎﻟﻀﺒﻂ ﺍﳌﺒﺎﺷﺮ ﻭﻫﻨﺎ ﻧﺴﺘﻄﻴﻊ ﺇﺿﺎﻓﺔ ﺍﻟﺸﻔﺮﺓ
ﺍﳋﺎﺻﺔ ﺑﺎﻟﺘﺤﻘﻖ ﻣﻦ ﺻﻼﺣﻴﺔ ﺍﻟﻘﻴﻤﺔ ،ﻛﺄﻥ ﺗﻜﻮﻥ ﺃﺻﻐﺮ ﻣﻦ ﺣﺪ ﻣﻌﲔ ،ﺃﻭ ﻏﲑ ﺳﺎﻟﺒﺔ ،ﺃﻭ ﺃﻭ ...
ﻛﻤﺎ ﺃﻥ ﻟﻠﺘﻐﻠﻴﻒ ﻣﻴﺰﺓ ﺳﺤﺮﻳﺔ ﻟﻠﻤﱪﻣﺞ ﻧﻔﺴﻪ ﻫﺬﺓ ﺍﳌﺮﺓ .. •
ﻹﺎ ﺗﺴﻤﺢ ﻟﺔ ﺑﺘﻐﻴﲑ ﺍﻟﺘﺮﻛﻴﺐ ﺍﻟﺪﺍﺧﻠﻲ ﻟﻠﺼﻨﻒ ﰲ ﺍﻟﺘﺤﺪﻳﺜﺎﺕ ﺍﳌﺴﺘﻘﺒﻠﻴﺔ ،ﻭﺑﺎﻟﺘﺎﱄ ﺳﺘﻄﺒﻖ ﺍﻟﺘﻐﻴﲑﺍﺕ ﺗﻠﻘﺎﺋﻴﺎ ﻋﻠﻰ ﺑﻘﻴﺔ
ﺍﻷﻏﺮﺍﺽ ﺍﻟﱵ ﺇﺳﺘﺨﺪﻣﺖ ﻫﺬﺍ ﺍﻟﺼﻨﻒ ﺑﺈﻗﻞ ﻋﻨﺎﺀ ﳑﻜﻦ ،ﺩﻭﻥ ﺍﳊﺎﺟﺔ ﻟﺘﻐﲑ ﺷﻔﺮﺗﻨﺎ ﰲ ﻣﻨﺎﻃﻖ ﳐﺘﻠﻔﺔ ﻣﻦ ﺍﻟﱪﻧﺎﻣﺞ .
ﻣﻼﺣﻈﺔ :
ﺑﺎﻹﺿﺎﻓﺔ ﺇﱃ ﺍﻟﺘﻐﻠﻴﻒ ﺍﳌﻌﺘﻤﺪ-ﻋﻠﻰ–ﺍﻟﺼﻨﻒ ﻓﺈﻥ ﺩﻟﻔﻲ ﺗﺪﻋﻢ ﺍﻟﺘﻐﻠﻴﻒ ﺍﳌﻌﺘﻤﺪ-ﻋﻠﻰ-ﺍﻟﻮﺣﺪﺓ ،ﲝﻴﺚ ﻛﻞ ﻣﺘﻐﲑ ﺗﻘﻮﻡ
ﺑﺘﻌﺮﻳﻔﺔ ﰲ ﻗﺴﻢ ﺍﻟـ Interfaceﻟﻠﻮﺣﺪﺓ ﺳﻴﺼﺒﺢ ﻣﺮﺋﻴﺎ ﻟﺒﺎﻗﻲ ﻭﺣﺪﺍﺕ ﺍﻟﱪﻧﺎﻣﺞ ﻋﻨﺪ ﺇﺳﺘﺨﺪﺍﻣﻬﺎ ﰲ ﺍﻟﺘﻌﺮﻳﻒ Usesﰲ
ﺣﲔ ﺃﻥ ﺍﳌﺘﻐﲑﺍﺕ ﺍﳌﻌﺮﻓﺔ ﰲ ﻗﺴﻢ ﺍﻟـ Implementationﻫﻲ ﻣﺘﻐﲑﺍﺕ ﳏﻠﻴﺔ ﳍﺬﺓ ﺍﻟﻮﺣﺪﺓ ﻓﻘﻂ .
١٠
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﻭﻫﻲ ، Private, Protected, Publicﺗﺘﺤﻜﻢ ﳏﺪﺩﺍﺕ ﺍﻟﻮﺻﻮﻝ ﲟﺠﺎﻝ ﺍﻟﺮﺅﻳﻪ ﺍﳌﺴﻤﻮﺡ ﺑﻪ ﻣﻦ ﺃﺟﻞ ﺣﻘﻞ ﺃﻭ ﻣﻨﻬﺞ ﻣﺎ
ﺍﻟﺘﻮﺟﻴﻪ Privateﻳﺪﻝ ﻋﻠﻰ ﺣﻘﻮﻝ ﺍﻟﺼﻨﻒ ﻭﻣﻨﺎﻫﺠﻪ ﺍﻟﱵ ﺗﻜﻮﻥ ﻏﲑ ﻣﺘﺎﺣﺔ ﺧﺎﺭﺝ ﺍﻟﻮﺣﺪﺓ ﺍﻟﱵ ﻋﺮﻑ ﻓﻴﻬﺎ •
ﺍﻟﺼﻨﻒ ،ﻭﻻ ﳝﻜﻦ ﺍﻟﻮﺻﻮﻝ ﺇﻟﻴﻬﺎ ﺳﻮﻯ ﻣﻦ ﺩﺍﺧﻞ ﻫﺬﻩ ﺍﻟﻮﺣﺪﺓ ،ﻭﺑﺎﻟﺘﺎﱄ ﻫﻲ ﻣﺘﻐﲑﺍﺕ ﳏﻠﻴﻪ ﰲ ﻫﺬﺓ ﺍﻟﻮﺣﺪﺓ
ﺗﺴﺘﺨﺪﻡ ﻹﲤﺎﻡ ﻋﻤﻞ ﺟﺰﺋﻲ ﻣﺎ ﺩﺍﺧﻞ ﺍﻟﺼﻨﻒ ﻭﻻ ﺩﺍﻋﻲ ﻟﻈﻬﻮﺭﻫﺎ ﻟﺒﻘﻴﺔ ﺍﻟﻌﻨﺎﺻﺮ .
ﺍﻟﺘﻮﺟﻴﻪ Protectedﻳﺴﺘﺨﺪﻡ ﻟﺘﺤﺪﻳﺪ ﳎﺎﻝ ﺭﺅﻳﻪ ﻣﻘﻴﺪ ﳊﻘﻮﻝ ﺍﻟﺼﻨﻒ ﻭﻣﻨﺎﻫﺠﻪ ،ﺣﻴﺚ ﻳﺴﺘﻄﻴﻊ ﺍﻟﺼﻨﻒ •
ﺍﳊﺎﱄ ﻭﺍﻷﺻﻨﺎﻑ ﺍﳌﻮﺭﺛﺔ ﻣﻨﺔ ﻓﻘﻂ ﺍﻟﻮﺻﻮﻝ ﺇﱃ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺍﳌﻌﺮﻓﺔ ﺿﻤﻨﻪ ،ﻭﺑﺒﺴﺎﻃﺔ ﻳﺴﺘﻄﻴﻊ ﺍﻟﺼﻨﻒ ﺍﻷﺳﺎﺳﻲ
ﻭﺍﻷﺻﻨﺎﻑ ﺍﳌﺸﺘﻘﺔ ﻣﻨﻪ ﺑﺎﻹﺿﺎﻓﺔ ﺇﱃ ﺃﻱ ﺷﻔﺮﺓ ﰲ ﻧﻔﺲ ﺍﻟﻮﺣﺪﺓ ﺍﻟﺪﺧﻮﻝ ﺇﱃ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺍﶈﻤﻴﺔ ﺑـ Protected
ﻭﻓﻘﻂ ﻫﺆﻻﺀ ﻫﻢ ﻣﻦ ﳝﻠﻜﻮﻥ ﲰﺎﺣﻴﺔ ﺍﻟﺪﺧﻮﻝ .ﻫﺬﺍ ﺍﻟﺘﻮﺟﻴﻪ ﻣﺜﻞ ﺳﺎﺑﻘﺔ ﻣﻦ ﻧﺎﺣﻴﺔ ﺃﻧﻪ ﳏﻠﻲ ﺿﻤﻦ ﺍﻟﻮﺣﺪﺓ ،
ﻭﻟﻜﻦ ﻧﻀﻴﻒ ﻫﻨﺎ ﺇﻣﻜﺎﻧﻴﺔ ﺍﻟﺮﺅﻳﺔ ﻣﻦ ﻗﺒﻞ ﺍﻷﺻﻨﺎﻑ ﺍﳉﺰﺋﻴﻪ ﺍﳌﺸﺘﻘﺔ ﺍﻟﱵ ﺭﲟﺎ ﲢﺘﺎﺝ ﻫﺬﺓ ﺍﻟﺒﻴﺎﻧﺎﺕ .
ﺍﻟﺘﻮﺟﻴﻪ Publicﻳﺪﻝ ﻋﻠﻰ ﺣﻘﻮﻝ ﻭﻣﻨﺎﻫﺞ ﳝﻜﻦ ﺍﻟﺪﺧﻮﻝ ﺇﻟﻴﻬﺎ ﲝﺮﻳﺔ ﻣﻦ ﺃﻱ ﺟﺰﺀ ﻣﻦ ﺍﻟﱪﻧﺎﻣﺞ ﻛﻤﺎ ﻟﻮ ﺃﺎ •
ﻣﻌﺮﻓﺔ ﺑﻨﻔﺲ ﺍﻟﻮﺣﺪﺓ ،ﺣﻴﺚ ﻻ ﺗﻮﺟﺪ ﻗﻴﻮﺩ ﰲ ﺍﻟﺪﺧﻮﻝ ﺇﱃ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺍﳌﻌﺮﻓﺔ ﺬﺍ ﺍﻟﺘﻮﺟﻴﺔ .
ﲢﺬﻳﺮ :
ﳏﺪﺩﺍﺕ ﺍﻟﻮﺻﻮﻝ ﺍﻟﺴﺎﺑﻘﺔ ﺗﻘﻮﻡ ﺑﺘﺤﺪﻳﺪ ﺇﻣﻜﺎﻧﻴﺔ ﺩﺧﻮﻝ ﺷﻔﺮﺍﺕ ﻣﻦ ﺧﺎﺭﺝ ﺍﻟﻮﺣﺪﺓ ﺇﱃ ﺍﻟﺼﻨﻒ ﺍﳌﻌﺮﻑ ﻓﻴﻬﺎ ،ﻭﺑﺎﻟﺘﺎﱄ
ﺇﺫﺍ ﻭﺟﺪ ﺻﻨﻔﺎﻥ ﰲ ﻧﻔﺲ ﺍﻟﻮﺣﺪﺓ ﻓﻼ ﺗﻮﺟﺪ ﲪﺎﻳﺔ ﻟﺪﺧﻮﻝ ﺇﺣﺪﳘﺎ ﺇﱃ ﺣﻘﻮﻝ ﺍﳌﻌﺮﻓﺔ Privateﻣﻦ ﺍﻟﺼﻨﻒ ﺍﻵﺧﺮ ..
ﺍﳋﺼﺎﺋﺺ ﺗﻌﺘﲑ ﻣﻦ ﺃﺭﻭﻉ ﺗﻘﻨﻴﺎﺕ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴﺔ ،ﻭﲤﺜﻞ ﻓﻜﺮﺓ ﺍﻟﺘﻐﻠﻴﻒ ﺑﺸﻜﻠﻬﺎ ﺍﻷﻣﺜﻞ .
ﻭﺍﳋﺼﺎﺋﺺ ﺑﺸﻜﻞ ﻋﺎﻡ ﻫﻲ ﺃﻭﻝ ﻣﺎ ﺗﻌﻠﻤﻨﺎ ﺍﻟﺘﻌﺎﻣﻞ ﻣﻌﻪ ﰲ ﻣﺮﺣﻠﺔ ﺍﳌﺒﺘﺪﺀ ،ﻭﻟﻠﺘﺒﺴﻴﻂ ﻓﺈﻥ ﻛﻞ ﻣﺎ ﺗﺮﺍﻩ ﰲ ﺿﺎﺑﻂ
ﺍﻟﻜﺎﺋﻨﺎﺕ ﻋﺒﺎﺭﺓ ﻋﻦ ﺧﺼﺎﺋﺺ ،ﻭﺍﻟﻔﻜﺮﺓ ﻫﻲ ﺃﻧﻚ ﺗﺘﻌﺎﻣﻞ ﻣﻊ ﺇﺳﻢ ،ﻭﺍﻟﺬﻱ ﳜﻔﻲ ﻋﻨﻚ ﺑﺸﻜﻞ ﻛﺎﻣﻞ ﺗﻔﺎﺻﻴﻞ ﺍﻟﺘﻨﻔﻴﺬ
،ﻭﺗﺼﺒﺢ ﻣﻬﻤﺘﻚ ﺍﳊﺎﻟﻴﺔ ﻛﻤﺴﺘﺨﺪﻡ ﻟﻠﺼﻨﻒ ﻫﻲ ﻗﺮﺍﺀﺓ ﺍﻟﻘﻴﻢ ﻣﻨﺔ ﺃﻭﻛﺘﺎﺑﺘﻬﺎ ﺇﻟﻴﺔ ،ﺃﻋﺠﺒﲏ ﺗﻌﺮﻳﻒ ﺃﺣﺪ ﺍﻟﻜﺘﺎﺏ ﻋﻨﺪﻣﺎ
ﻗﺎﻝ ﺃﻥ ﺍﳋﺼﺎﺋﺺ ﻫﻲ ﺣﻘﻮﻝ ﺇﻓﺘﺮﺍﺿﻴﻪ ). (virtual fields
١١
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﺭﲟﺎ ﻻﺣﻈﺖ ﰲ ﺍﻟﻔﻘﺮﺓ ﺍﻟﺴﺎﺑﻘﺔ ﺃﻧﻨﺎ ﳚﺐ ﺃﻥ ﻧﺪﺧﻞ ﻟﻠﺒﻴﺎﻧﺎﺕ ﰲ ﺣﺎﻟﺔ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴﺔ ﻋﻦ ﻃﺮﻳﻖ ﺍﳌﻨﺎﻫﺞ ﺑﺪﻻ ﻣﻦ
ﺍﻟﺪﺧﻮﻝ ﺍﳌﺒﺎﺷﺮ ،ﻭﻫﺬﺍ ﻳﺒﺪﻭ ﺷﻴﺌﺎ ﻣﺮﺑﻜﺎ ﻗﻠﻴﻼ ،ﺧﺎﺻﺔ ﺃﻥ ﻣﻨﻬﺞ ﺍﻟﻘﺮﺍﺀﺓ ﺳﻴﻜﻮﻥ ﳐﺘﻠﻒ ﻋﻦ ﻣﻨﻬﺞ ﺍﻟﻜﺘﺎﺑﺔ ،
ﺇﺫﺍ ﺑﻨﻴﻨﺎ ﺣﻘﻮﻝ ﺇﻓﺘﺮﺍﺿﻴﺔ ﺗﺴﺘﺨﺪﻡ ﻫﺬﺓ ﺍﳌﻨﺎﻫﺞ ﻭﲣﻔﻴﻬﺎ ﻋﻨﺎ ﻓﺈﻧﻨﺎ ﺳﻨﻜﺴﺐ ﺳﻬﻮﻟﺔ ﺍﻟﺪﺧﻮﻝ ﺍﳌﺒﺎﺷﺮ ﻟﻠﺒﻴﺎﻧﺎﺕ ﻭﻗﻮﺓ
ﺍﻟﺘﻐﻠﻴﻒ .ﻫﺬﺓ ﺍﳊﻘﻮﻝ ﺍﻹﻓﺘﺮﺍﺿﻴﺔ ﻫﻲ ﺍﳋﺼﺎﺋﺺ ،ﻭﻧﺘﻌﺎﻣﻞ ﻣﻌﻬﺎ ﻣﺜﻠﻤﺎ ﻧﺘﻌﺎﻣﻞ ﻣﻊ ﺍﳊﻘﻮﻝ ﺍﻟﻌﺎﺩﻳﺔ .
Captionﻣﻦ ﺍﻟﻐﺮﺽ Button1 ﻻﺣﻆ ﺃﻧﺎﻥ ﺇﺳﺘﺨﺪﻣﻨﺎ ﺍﳋﺎﺻﻴﺔ Textﺍﳌﺘﻌﻠﻘﺔ ﺑﺎﻟﻐﺮﺽ Edit1ﻟﻠﻜﺘﺎﺑﺔ ﻓﻴﻬﺎ ،ﻭﺍﳋﺎﺻﻴﺔ
ﻟﻠﻘﺮﺍﺀﺓ ﻣﻨﻬﺎ .ﻭﺑﺒﺴﺎﻃﺔ ﺃﺻﺒﺤﻨﺎ ﺬﺓ ﺍﻟﻔﻜﺮﺓ ﺍﻟﺮﺍﺋﻌﺔ ﻧﻀﻴﻊ ﺍﻟﻮﻗﺖ ﺑﺎﻟﺘﻔﻜﲑ ﺑﺪﻻ ﻣﻦ ﺇﺿﺎﻋﺔ ﺍﻟﻮﻗﺖ ﺑﻜﺘﺎﺑﺔ ﺍﻟﺸﻔﺮﺓ ،
ﺑﺎﻟﺘﺄﻛﻴﺪ ﺗﻮﺟﺪ ﻣﻨﺎﻫﺞ ﺧﺎﺻﺔ ﻟﻠﻜﺘﺎﺑﺔ ﺇﱃ ﺍﳋﺎﺻﻴﺔ Textﻭﻟﻠﻘﺮﺍﺀﺓ ﻣﻨﻬﺎ ،ﻟﻜﻦ ﺍﳋﺎﺻﻴﺔ Textﺃﺧﻔﺖ ﻫﺬﺓ ﺍﻹﺭﺑﺎﻛﺎﺕ
ﻋﻨﺎ ﻭﲰﺤﺖ ﻟﻨﺎ ﺑﺈﺳﺘﺨﺪﺍﻣﻬﺎ ﺑﻐﺾ ﺍﻟﻨﻈﺮ ﻋﻦ ﻣﻌﺮﻓﺘﻨﺎ ﺑﺸﻔﺮﺎ ﺍﳌﺨﻔﻴﺔ ﳏﻘﻘﺔ ﺑﺬﻟﻚ ﺗﻐﻠﻴﻔﺎ ﻣﺜﺎﻟﻴﺎﹰ .
ﺍﻟﻔﻘﺮﻩ ﺍﻟﺴﺒﻘﺔ ﺗﻜﻠﻤﺖ ﻋﻦ ﻣﺴﺘﺨﺪﻡ ﺍﻟﺼﻨﻒ ﺍﻟﺬﻱ ﻳﺴﺘﻄﻴﻊ ﺇﺳﺘﺨﺪﺍﻡ ﺍﳋﻮﺍﺹ ﺑﺴﻬﻮﻟﺔ ،ﻫﺬﺓ ﺍﻟﻔﻘﺮﺓ ﺳﺘﺘﻜﻠﻢ ﻋﻦ ﺑﺎﱐ
ﺍﻟﺼﻨﻒ ﺍﻟﺬﻱ ﻳﺆﻣﻦ ﻫﺬﺓ ﺍﻟﺴﻬﻮﻟﺔ .
ﻭﺑﻨﺎﺀ ﻋﻠﻰ ﺫﻟﻚ ﻟﺘﻌﺮﻳﻒ ﺧﺎﺻﻴﺔ ﻣﺎ ﳓﻦ ﳓﺘﺎﺝ ﻟﺘﻌﺮﻳﻒ ﻗﺎﺑﻠﻴﺔ ﺍﻟﻘﺮﺍﺀﺓ ﻭﻗﺎﺑﻠﻴﺔ ﺍﻟﻜﺘﺎﺑﺔ ﺃﻳﻀﺎ ،ﻭﻳﺘﻢ ﺫﻟﻚ ﺑﺒﺴﺎﻃﺔ ﻋﻦ
ﻃﺮﻳﻖ ﺍﻟﻜﻠﻤﺘﲔ ﺍﳌﻔﺘﺎﺣﻴﺘﲔ Read , Writeﻛﻤﺎ ﺃﻧﻨﺎ ﻧﺴﺘﺨﺪﻡ ﺍﻟﻜﻠﻤﺔ ﺍﶈﺠﻮﺯﺓ propertyﻟﺘﻌﺮﻳﻒ ﺧﺎﺻﻴﺔ ﺟﺪﻳﺪﺓ
ﺃﻣﺜﻠﺔ:
;1- property Month: Integer read FMonth write FMonth
ﺣﻴﺚ Fmonthﻣﺘﻐﲑ ﻣﻌﺮﻑ ﻛـ ، Privateﻭ SetMonthﺇﺟﺮﺍﺋﻴﺔ ﻭ GetMonthﺗﺎﺑﻊ ﻣﻌﺮﻓﺎﻥ ﺿﻤﻦ ﺍﻟﺼﻨﻒ .
١٢
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﺍﳊﺎﻟﺔ ﺍﻷﻭﱃ :ﻭﻫﻲ ﺃﺑﺴﻂ ﺍﳊﺎﻻﺕ ،ﺃﻥ ﻧﻘﻮﻡ ﺑﺘﻌﺮﻳﻒ ﻣﺘﺤﻮﻝ ﻣﺎ Fmonthﻣﺜﻼ ﻣﻦ ﺃﺟﻞ ﺍﻟﻘﺮﺍﺀﺓ ﻭﺍﻟﻜﺘﺎﺑﺔ ،ﺑﺪﻭﻥ
ﺇﺳﺘﺨﺪﺍﻡ ﺃﻱ ﻣﻨﻬﺞ ،ﺍﻟﻘﺮﺍﺀﺓ ﺗﺘﻢ ﻣﻨﻪ ﻭﺍﻟﻜﺘﺎﺑﺔ ﺇﻟﻴﺔ ،ﻭﻃﺒﻌﺎ ﻻ ﳝﻜﻦ ﻫﻨﺎ ﺍﻟﺘﺄﻛﺪ ﻣﻦ ﺻﺤﺔ ﺍﻹﺩﺧﺎﻝ ،ﺃﻭ ﺇﺭﻓﺎﻕ ﺇﺩﺧﺎﻝ
ﺃﻭ ﺇﺧﺮﺍﺝ ﺍﻟﻘﻴﻤﺔ ﲝﺪﺙ ﻣﺎ .
ﺍﳊﺎﻟﺔ ﺍﻟﺜﺎﻧﻴﺔ :ﻗﻤﻨﺎ ﺑﺎﻟﻘﺮﺍﺀﺓ ﻣﻦ ﻣﺘﺤﻮﻝ ) (Fmonthﺑﺸﻜﻞ ﻃﺒﻴﻌﻲ ﻣﺜﻞ ﺍﳊﺎﻟﺔ ﺍﻷﻭﱃ ،ﺣﻴﺚ ﺃﻧﺔ ﰲ ﻛﺜﲑ ﻣﻦ ﺍﻷﺣﻴﺎﻥ
ﻻ ﳓﺘﺎﺝ ﺍﻟﺘﺄﻛﺪ ﻣﻦ ﺻﺤﺔ ﺍﻹﺧﺮﺍﺝ ﻃﺎﳌﺎ ﻛﻨﺎ ﻗﺪ ﺗﺄﻛﺪﻧﺎ ﻣﻦ ﺻﺤﺔ ﺍﻹﺩﺧﺎﻝ ﻣﻨﺬ ﺍﻟﺒﺪﺍﻳﺔ .
ﺃﻣﺎ ﺍﻟﻜﺘﺎﺑﺔ ﻓﺘﺘﻢ ﺑﺈﺳﺘﺨﺪﺍﻡ ﺍﻹﺟﺮﺍﺋﻴﺔ ، SetMonthﻭﻫﻨﺎ ﻧﺴﺘﻄﻴﻊ ﺍﻟﺘﺄﻛﺪ ﻣﻦ ﺻﻼﺣﻴﺔ ﺍﻷﺩﺧﺎﻝ ﺃﻭ ﺇﺭﻓﺎﻕ ﺍﻹﺩﺧﺎﻝ
ﺑﺄﺣﺪﺍﺙ ﻣﺎ )ﺇﻟﻐﺎﺀ ﺗﻌﻄﻴﻞ ﺧﻮﺍﺹ ﻣﻌﻴﻨﺔ ﺑﻌﺪ ﺍﻹﺩﺧﺎﻝ ﻣﺜﻼ( ،ﻭﺑﺎﻟﻄﺒﻊ ﻫﺬﺓ ﺍﳊﺎﻟﺔ ﻣﺴﺘﺨﺪﻣﺔ ﻛﺜﲑﺍ ﻋﻠﻰ ﻋﻜﺲ ﺍﳊﺎﻟﺔ
ﺍﻷﻭﱃ .
ﺍﳊﺎﻟﺔ ﺍﻟﺜﺎﻟﺜﺔ :ﺇﺳﺘﺨﺪﻣﻨﺎ ﺍﻟﺘﺎﺑﻊ GetMonthﻟﻺﺩﺧﺎﻝ ﻭﺍﻹﺟﺮﺍﺋﻴﺔ SetMonthﻟﻺﺧﺮﺍﺝ ،ﻭﻫﻲ ﺍﳊﺎﻟﺔ ﺍﻟﻌﺎﻣﺔ .
ﻣﻼﺣﻈﺔ :ﻗﺮﺍﺀﺓ ﺍﳋﺎﺻﻴﺔ ﺳﺘﻌﻴﺪ ﻗﻴﻤﺔ ﻭﺍﺣﺪﺓ ﻣﻨﻬﺎ ،ﻭﺑﺎﻟﺘﺎﱄ ﻣﻦ ﺍﳌﺜﺎﱄ ﻫﻨﺎ ﺇﺳﺘﺨﺪﻡ ﺗﺎﺑﻊ ) (Functionﻟﻠﻘﺮﺍﺀﺓ .
ﺍﻟﻜﺘﺎﺑﺔ ﻟﻦ ﺗﻌﻴﺪ ﻗﻴﻢ ﻭﻟﻜﻨﻬﺎ ﺳﺘﺪﺧﻞ ﻗﻴﻤﺔ ﺿﻤﻦ ﺑﺎﺭﺍﻣﺘﺮﺍﺕ ﺍﳌﻨﻬﺞ ،ﻟﺬﻟﻚ ﻧﺴﺘﺨﺪﻡ ﺇﺟﺮﺍﺋﻴﺔ ) (Procedureﻟﻠﻜﺘﺎﺑﺔ .
ﻋﺎﺩﺓ ﺗﻜﻮﻥ ﺣﻘﻮﻝ ﺍﻟﺒﻴﺎﻧﺎﺕ ﻭﻣﻨﺎﻫﺞ ﺍﻟﺪﺧﻮﻝ ﺍﻟﺴﺎﺑﻘﺔ ) Privateﻭﻣﻦ ﺍﳌﻤﻜﻦ ﺃﻥ ﺗﻜﻮﻥ (Protected
ﻭﻫﺬﺍ ﻳﻌﻄﻲ ﺩﺭﺟﺔ ﻣﺜﺎﻟﻴﺔ ﻣﻦ ﺍﻟﺘﻐﻠﻴﻒ ،ﻹﻧﻚ ﺗﺴﺘﻄﻴﻊ ﺗﻐﻴﲑ ﺑﻴﺎﻧﺎﺕ ﺍﻟﺼﻨﻒ ﺃﻭ ﻣﻨﺎﻫﺞ ﺍﻟﻘﺮﺍﺀﺓ ﻭﺍﻟﻜﺘﺎﺑﺔ )ﻭﺍﻟﱵ ﻫﻲ ﻏﲑ
ﻣﺮﺋﻴﺔ ﳌﺴﺘﺨﺪﻡ ﺍﻟﺼﻨﻒ ( ﺩﻭﻥ ﺃﻥ ﻳﺘﺄﺛﺮ ﺎ ﻣﺴﺘﺨﺪﻡ ﺍﻟﺼﻨﻒ ﻭﻟﻦ ﻳﻀﻄﺮ ﻟﺘﻐﻴﲑ ﺷﻔﺮﺗﺔ ﻹﻧﺔ ﻳﺴﺘﺨﺪﻡ ﺃﲰﺎﺀ ﺍﳋﻮﺍﺹ
ﻓﻘﻂ ﻭ ﺍﻟﱵ ﺑﻘﻴﺖ ﺛﺎﺑﺘﺔ ،ﰲ ﺣﲔ ﺃﻥ ﻛﻞ ﺍﻟﺘﻐﲑﺍﺕ ﰲ ﻃﺮﻳﻘﺔ ﺍﻟﻘﺮﺍﺀﺓ ﻭﺍﻟﻜﺘﺎﺑﺔ ﻟﻦ ﺗﺆﺛﺮ ﻋﻠﻴﺔ ..
ﺗﺬﻛﺮ ﺍﻟﺼﻨﺪﻭﻕ ﺍﻷﺳﻮﺩ ،ﺍﳌﺴﺘﺨﺪﻡ ﳝﻠﻚ ﺇﺳﻢ ﺍﳋﺎﺻﻴﺔ ﻭﻳﺘﻌﺎﻣﻞ ﻣﻌﻬﺎ ،ﻃﺎﳌﺎ ﺑﻘﻲ ﺇﺳﻢ ﺍﳋﺎﺻﻴﺔ ﺛﺎﺑﺘﺎ ﻓﺈﻥ ﻋﻤﻠﺔ ﻟﻦ
ﻳﺘﺄﺛﺮ ﺑﺄﻱ ﺗﻐﻴﲑ .
١٣
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﻣﺜﺎﻝ ﻋﻤﻠﻲ
----------
ﺍﳍﺪﻑ :ﺍﻟﺘﺪﺭﻳﺐ ﻋﻠﻰ ﺑﻨﺎﺀ ﺃﺻﻨﺎﻑ ﺟﺪﻳﺪﺓ ،ﻭﺗﻄﺒﻴﻖ ﻣﺎ ﺗﻌﻠﻤﻨﺎﺓ ﰲ ﺍﻟﻔﻘﺮﺍﺕ ﺍﻟﺴﺎﺑﻘﺔ ﻣﻦ ﺇﻧﺸﺎﺀ ﺍﳌﻨﺎﻫﺞ ﻭﺍﳋﺼﺎﺋﺺ
ﻭﺍﻟﺘﻌﺎﻣﻞ ﻣﻊ ﳏﺪﺩﺍﺕ ﺍﻟﻮﺻﻮﻝ .
ﻣﺎﺫﺍ ﻧﺮﻳﺪ ﻣﻦ ﺍﻟﺼﻨﻒ ،،ﺍﻟﻘﺮﺍﺀﺓ ﻣﻨﺔ ﻭﺍﻟﻜﺘﺎﺑﺔ ﺇﻟﻴﺔ ،ﺑﺎﻹﺿﺎﻓﺔ ﺇﱃ ﺇﺟﺮﺍﺀ ﺑﻌﺾ ﺍﻟﺘﺤﻜﻤﺎﺕ ﻭﺍﻟﻌﻤﻠﻴﺎﺕ ﺍﳌﻔﻴﺪﺓ .ﻭﻟﻜﻲ
ﳝﻠﻚ ﺍﳌﺜﺎﻝ ﺻﻔﺔ ﻣﺴﺄﻟﺔ ﲝﻴﺚ ﳝﻜﻨﻚ ﲡﺮﻳﺐ ﺣﻠﻬﺎ ﻟﻮﺣﺪﻙ ،ﺳﺄﻗﻮﻡ ﺑﺘﻔﺼﻴﻞ ﺫﻟﻚ :
ﻣﻊ ﻣﺮﺍﻋﺎﺓ ﺍﳋﻮﺍﺹ ﺍﻟﺘﺎﻟﻴﺔ: ﺑﺎﻹﺳﻢ Tdate ﺍﳌﻄﻠﻮﺏ :ﺑﻨﺎﺀ ﺻﻨﻒ ﺟﺪﻳﺪ
-ﺇﻣﻜﺎﻧﻴﺔ ﺿﺒﻂ ﺍﻟﻘﻴﻤﺔ ﺑﻄﺮﻳﻘﺘﲔ .ﺃﻭﻻ :ﻋﻦ ﻃﺮﻳﻖ ﺇﺩﺧﺎﻝ ﺛﻼﺙ ﻗﻴﻢ ﻟﻠﻴﻮﻡ ﻭﺍﻟﺸﻬﺮ ﻭﺍﻟﺴﻨﺔ ،ﺛﺎﻧﻴﺎ :ﻋﻦ ﻃﺮﻳﻖ ﺇﺩﺧﺎﻝ
ﻗﻴﻤﺔ ﻭﺍﺣﺪﺓ ﻣﻦ ﺍﻟﻨﻤﻂ TdateTime
-ﻭﺟﻮﺩ ﻣﻨﻬﺞ ﺯﻳﺎﺩﺓ ﻳﻮﻡ ،ﲝﻴﺚ ﻳﺰﻳﺪ ﻳﻮﻡ ﻟﻠﺘﺎﺭﻳﺦ ﺍﳌﺨﺰﻥ ﻛﻠﻤﺎ ﰎ ﺗﻨﻔﻴﺬﺓ .
-ﻭﺟﻮﺩ ﺛﻼﺙ ﺧﺼﺎﺋﺺ Year , Month , Dayﳝﻜﻦ ﺍﻟﺘﻌﺎﻣﻞ ﻣﻌﻬﺎ )ﻗﺮﺍﺀﺓ ﻭﻛﺘﺎﺑﺔ ﺇﱃ ﻛﻞ ﻣﻨﻬﺎ ( .
ﺗﺬﻛﺮ ﺃﻧﺔ ﻻﻳﻮﺟﺪ ﺷﻲﺀ ﰲ ﺍﻟﱪﳎﺔ ﻳﺘﻢ ﻋﻤﻠﺔ ﺩﻓﻌﺔ ﻭﺍﺣﺪﺓ ،ﻟﺬﻟﻚ ﺳﻨﻘﻮﻡ ﺑﺒﻨﺎﺀ ﺍﻟﺼﻨﻒ ﺧﻄﻮﺓ ﺧﻄﻮﺓ ﻭﺗﻌﺪﻳﻞ ﺷﻔﺮﺗﻨﺎ
ﻛﻞ ﻣﺮﺓ ﻛﺄﻧﻨﺎ ﻧﻌﻤﻞ ﻋﻠﻰ ﺣﻮﺍﺳﻴﺒﻨﺎ ﺍﻟﺸﺨﺼﻴﺔ ﻣﻨﺬ ﺍﻟﺒﺪﺍﻳﺔ .
ﻃﺮﻳﻘﱵ ﺑﺎﻟﻌﻤﻞ ﻫﻲ ﺍﻟﻄﺮﻳﻘﺔ ﺍﻟﺘﺮﺍﺟﻌﻴﺔ ﲝﻴﺚ ﻧﻨﻄﻠﻖ ﻣﻦ ﺍﻵﺧﺮ ﺣﱴ ﻧﺼﻞ ﺇﱃ ﺍﻟﺒﺪﺍﻳﺔ ،ﻣﺜﻼ ﺩﻋﻨﺎ ﻧﻔﻜﺮ ﻛﻴﻒ ﺳﻴﺼﺒﺢ
ﺍﻟﺼﻨﻒ ﺍﳉﺪﻳﺪ ﻭﻣﺎ ﻫﻲ ﺧﺼﺎﺋﺼﺔ ﻭﻣﻨﺎﻫﺠﻪ ﻗﺒﻞ ﺍﻟﺒﺪﺀ ﺑﺎﻟﻌﻤﻞ .
١٤
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
،ﻭﻗﺪ ﺗﻌﻠﻤﻨﺎ ﺫﻟﻚ ﺳﺎﺑﻘﺎ ﻭﻫﻮ ﺳﻬﻞ : ﺑﺎﻹﺳﻢ Tdate ﺃﻭﻻ ﻋﻠﻲ ﺃﻥ ﺃﻗﻮﻡ ﺑﺒﻨﺎﺀ ﺻﻨﻒ ﺟﺪﻳﺪ
type
TDate = class
-ﻣﻨﻬﺞ "ﺿﺒﻂ ﺍﻟﻘﻴﻤﺔ" ﻟﻦ ﻳﺮﺟﻊ ﺃﻱ ﻗﻴﻢ ﺑﻞ ﺳﻨﻤﺮﺭ ﻟﺔ ﺍﻟﻘﻴﻢ ﻋﻠﻰ ﺷﻜﻞ ﺑﺎﺭﺍﻣﺘﺮﺍﺕ ،ﻟﺬﻟﻚ ﻣﻦ ﺍﻷﻧﺴﺐ ﺃﻥ ﻳﻜﻮﻥ
ﺇﺟﺮﺍﺋﻴﺔ Procedureﻭﻟﻴﺲ ﺗﺎﺑﻌﺎ ، Function
ﻧﺮﻳﺪ
ﻧﺮﻳﺪ ﺇﺟﺮﺍﺋﻴﺘﲔ ﳐﺘﻠﻔﺘﲔ ﻟﻀﺒﻂ ﺍﻟﻘﻴﻤﺔ ،ﻭﻟﻜﻦ ﺗﺬﻛﺮ ﺃﻧﺔ ﺑﺈﻣﻜﺎﻧﻨﺎ ﺇﺳﺘﺨﺪﺍﻡ ﻧﻔﺲ ﺍﻹﺳﻢ ﻟﻜﻼ ﺍﻹﺟﺮﺍﺋﻴﺘﲔ ﻭﺫﻟﻚ
ﺑﺎﻹﺳﺘﻔﺎﺩﺓ ﻣﻦ ﺧﺎﺻﻴﺔ ﺍﻟﺘﺤﻤﻴﻞ ﺍﻟﺰﺍﺋﺪ ﰲ ﺩﻟﻔﻲ )ﺣﻴﺚ ﺳﻴﻜﻮﻥ ﺍﻟﻔﺮﻕ ﺑﺎﻟﱪﺍﻣﺘﺮﺍﺕ( ،ﻭﺳﺄﺧﺘﺎﺭ ﺇﲰﺎ ﻣﻨﺎﺳﺒﺎ ﳍﻤﺎ ﻭﻟﻴﻜﻦ
". " SetValue
-ﻧﺮﻳﺪ ﺃﻳﻀﺎ ﻣﻨﻬﺞ ﻟﻴﻌﺮﻑ ﺇﺫﺍ ﻛﺎﻧﺖ ﺍﻟﺴﻨﺔ ﻛﺒﻴﺴﺔ ﺃﻭ ﻻ ،ﻣﻦ ﺍﳌﻼﺣﻆ ﺃﻧﺔ ﺳﻴﻌﻴﺪ ﻗﻴﻤﻴﺔ ﺑﻮﻟﻴﺎﻧﻴﺔ ﻭﺍﺣﺪﺓ ،ﻟﺬﻟﻚ ﻣﻦ
ﺍﳌﻨﺎﺳﺐ ﺃﻥ ﻳﻜﻮﻥ ﺗﺎﺑﻌﺎ Functionﻭﻟﻴﺲ ﺇﺟﺮﺍﺋﻴﺔ Procedureﻭﻟﻴﻜﻦ ﺇﲰﺔ " ، " LeapYearﻭﺳﻴﺒﺪﻭ ﺷﻜﻠﺔ ﺑﻌﺪ
ﺍﻹﻧﺘﻬﺎﺀ ﻛﺎﻟﺘﺎﱄ :
;)'If (TheDate. LeapYear) then showmessage('Leap Year
ﻣﻨﻬﺞ ﺇﺧﺮﺍﺝ ﺍﻟﺘﺎﺭﻳﺦ ﺑﺸﻜﻞ ﻧﺼﻲ ﻣﺸﺎﺑﻪ ﳊﺎﻟﺔ ﺗﺎﺑﻊ ﺍﻟﺴﻨﺔ ﺍﻟﻜﺒﻴﺴﺔ ﻹﻧﺔ ﺳﻴﻌﻴﺪ ﻗﻴﻤﺔ ﻧﺼﻴﻪ ﻭﺍﺣﺪﺓ ،ﻭﺑﺎﻟﺘﺎﱄ ﺳﻴﻜﻮﻥ
ﺗﺎﺑﻌﺎ ﻭﺳﻴﻜﻮﻥ ﺷﻜﻠﺔ ﺑﻌﺪ ﺍﻹﻧﺘﻬﺎﺀ ﻛﺎﻟﺘﺎﱄ :
;)showmessage(TheDate.GetText
-ﻣﻨﻬﺞ ﺯﻳﺎﺩﺓ ﺍﻟﻴﻮﻡ ﻟﻴﺲ ﲝﺎﺟﺔ ﺃﺻﻼ ﻟﺒﺎﺭﺍﻣﺘﺮﺍﺕ ،ﻹﻥ ﻣﻘﺪﺍﺭ ﺍﻟﺰﻳﺎﺩﺓ ﳏﺪﺩﺓ ﺳﻠﻔﺎ ﺣﻴﺚ ﺳﻴﺰﻳﺪ ﺍﻟﺘﺎﺑﻊ ﻳﻮﻡ ﻭﺍﺣﺪ
ﻓﻘﻂ ﻋﻨﺪ ﻛﻞ ﻣﺮﺓ ﻳﺘﻢ ﺇﺳﺘﺪﻋﺎﺀﺓ ﻓﻴﻬﺎ ،ﻭﻟﻴﻜﻦ ﺇﲰﺔ " "Increase
١٥
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﺇﻥ ﻛﻞ ﻣﻦ ﺍﻹﺣﺪﺍﺙ ﺍﻟﺴﺎﺑﻘﺔ ﳚﺐ ﺃﻥ ﻳﻜﻮﻥ ﻣﺮﺋﻴﺎ ﻣﻦ ﻛﻞ ﺍﻟﻮﺣﺪﺍﺕ ﻭﻳﺴﺘﻄﻴﻊ ﺍﳌﺴﺘﺨﺪﻡ ﺇﺳﺘﺨﺪﺍﻣﺔ ﺑﺸﻜﻞ
ﺍﻟﺘﻮﺟﻴﺔ . Public ﻃﺒﻴﻌﻲ ،ﻭﺑﺎﻟﺘﺎﱄ ﳚﺐ ﺃﻥ ﻳﻌﺮﻑ ﲢﺖ
ﻭﻣﺎ ﺃﺻﺒﺤﻨﺎ ﻧﻌﺮﻓﺔ ﺍﻵﻥ ﺃﻧﻨﺎ ﳕﻠﻚ ﺻﻨﻒ Tdateﻟﺔ ﺍﳌﻨﺎﻫﺞ ﺍﻟﻌﺎﻣﺔ ﺍﻟﺴﺎﺑﻘﺔ ﻭﺑﺎﻟﺘﺎﱄ ﺃﺻﺒﺢ ﺍﻟﺘﻌﺮﻳﻒ ﺳﻬﻼ ،ﻭﺣﱴ ﻫﺬﺓ
ﺍﳌﺮﺣﻠﺔ ﳝﻜﻨﻨﺎ ﺃﻥ ﻧﻜﺘﺐ ﺍﻟﺘﻌﺮﻳﻒ ﻛﺎﻟﺘﺎﱄ :
type
TDate = class
public
;procedure Increase
;end
ﺍﳋﺼﺎﺋﺺ ﺍﳌﻄﻠﻮﺑﺔ Yearﻭ Monthﻭ Dayﲢﺘﺎﺝ ﺇﱃ ﻗﺮﺍﺀﺓ ﻭﻛﺘﺎﺑﺔ ﺑﺎﻟﺘﺄﻛﻴﺪ ،ﻭﺳﺄﺧﺘﺎﺭ ﻫﻨﺎ ﺍﳊﺎﻟﺔ ﺍﻟﻌﺎﻣﺔ ﻭﺃﺿﻊ ﺗﺎﺑﻊ
ﻟﻠﻘﺮﺍﺀﺓ ﻭﺇﺟﺮﺍﺋﻴﺔ ﻟﻠﻜﺘﺎﺑﺔ .
ﻓﺈﺫﺍ ﲰﻴﻨﺎ ﺗﺎﺑﻊ ﺍﻟﻘﺮﺍﺀﺓ GetYearﻭﺇﺟﺮﺍﺋﻴﺔ ﺍﻟﻜﺘﺎﺑﺔ SetYearﺳﺘﺼﺒﺢ ﺍﻟﺘﻌﺎﺭﻳﻒ ﺍﻟﺜﻼﺛﺔ ﻛﺎﻟﺘﺎﱄ :
;property Year: Integer read GetYear write SetYear
ﺑﺎﻟﺘﺄﻛﻴﺪ ﲟﺎ ﺃﻥ ﺍﳋﻮﺍﺹ ﳚﺐ ﺃﻥ ﺗﻜﻮﻥ ﻇﺎﻫﺮﺓ ﻟﻠﻤﺴﺘﺨﺪﻡ ﻭﻟﺒﻘﻴﺔ ﺍﻟﻮﺣﺪﺍﺕ ﻓﻬﻲ ﰲ ﻗﺴﻢ Publicﻛﺬﻟﻚ ،
١٦
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
GetYear , ﻭﺍﻟﺸﻲﺀ ﺍﳌﻬﻢ ﻫﻨﺎ ﻫﻮ ﺃﻥ ﺍﻟﺘﻮﺍﺑﻊ ﻭﺍﻹﺟﺮﺍﺀﺍﺕ ﺍﳋﺎﺻﺔ ﺑﺎﻟﻘﺮﺍﺀﺓ ﻭﺍﻟﻜﺘﺎﺑﺔ ﺍﻟﱵ ﺍﺳﺘﺨﺪﻣﺘﻬﺎ ﺍﳋﻮﺍﺹ ﺍﻟﺴﺎﺑﻘﺔ ﻣﺜﻞ
ﻭﺑﺎﻟﺘﺎﱄ، ﻫﻲ ﻣﻨﺎﻫﺞ ﳏﻠﻴﺔ ﻭﻻﳚﺐ ﻋﻠﻰ ﺍﳌﺴﺘﺨﺪﻡ ﺃﻥ ﻳﺮﺍﻫﺎ ﻭﻳﺴﺘﻌﻤﻠﻬﺎ ﻹﻧﺔ ﻳﺴﺘﻌﻤﻞ ﺍﳋﺎﺻﺔ ﺍﻷﺳﺎﺳﻴﺔ ﻣﺒﺎﺷﺮﺓSetYear
. ﺣﻴﺚ ﻟﻦ ﺗﻜﻮﻥ ﻣﺮﺋﻴﺔ ﺧﺎﺭﺝ ﻫﺬﺓ ﺍﻟﻮﺣﺪﺓ، private ﺳﻨﻘﻮﻡ ﺑﺘﻌﺮﻳﻔﻬﺎ ﺑﺸﻜﻞ ﳏﻠﻲ ﺿﻤﻦ ﺍﻟﺘﻮﺟﻴﺔ
ﻻ ﺗﻨﺴﻰ ﺃﻧﻚ ﺗﻀﺒﻂ، ﺑﻘﻲ ﻟﺪﻳﻨﺎ ﺍﻵﻥ ﺷﻲﺀ ﻭﺣﻴﺪ ﱂ ﻧﺄﺧﺬﺓ ﺑﺎﳊﺴﺒﺎﻥ ﻭﻫﻮ ﺍﳌﺘﺤﻮﻝ ﺍﻟﺬﻱ ﺳﻮﻑ ﳔﺰﻥ ﻗﻴﻤﺔ ﺍﻟﺘﺎﺭﻳﺦ ﻓﻴﺔ
. ﻭﺑﺎﻟﺘﺎﱄ ﳓﻦ ﲝﺎﺟﺔ ﳌﺘﺤﻮﻝ ﳊﻔﻆ ﺍﻟﺘﺎﺭﻳﺦ، ﻗﻴﻤﺔ ﺍﻟﺼﻨﻒ ﻣﺮﺓ ﻭﺍﺣﺪﺓ ﰒ ﺗﺴﺘﺪﻋﻲ ﺍﳌﻨﺎﻫﺞ ﺍﻟﺴﺎﺑﻘﺔ ﻟﻠﺘﺎﺭﻳﺦ ﺍﶈﻔﻮﻅ ﺿﻤﻨﺔ
Private ﻭﻃﺒﻌﺎ ﻻﺣﻈﺖ ﺃﻧﺔ ﳚﺐ ﺃﻥ ﻳﻌﺮﻑ ﳏﻠﻴﺎ ﺿﻤﻦ ﻗﺴﻢ، TdateTime ﻣﻦ ﺍﻟﻨﻤﻂfDate ﻭﻟﻴﻜﻦ ﻫﺬﺍ ﺍﳌﺘﺤﻮﻝ ﻫﻮ
. ﻛﺬﻟﻚ
: ﻛﺎﻟﺘﺎﱄInterface ﺃﺻﺒﺢ ﺍﻵﻥ ﺷﻜﻞ ﺍﻟﺘﻌﺮﻳﻒ ﺍﻟﻨﻬﺎﺋﻲ ﺍﻟﺬﻱ ﺳﻨﻀﻌﺔ ﰲ ﻗﺴﻢ ﺍﻟـ
type
TDate = class
private
fDate: TDateTime;
public
procedure Increase;
١٧
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
;end
ﺗﺬﻛﲑ :ﻟﻜﺘﺎﺑﺔ ﺃﺟﺴﺎﻡ ﺍﳌﻨﺎﻫﺞ ﻧﻀﻴﻒ ﺇﺳﻢ ﺍﻟﺼﻨﻒ ﻣﻔﺼﻮﻻ ﺑﻨﻘﻄﺔ ﻋﻦ ﺇﺳﻢ ﺍﳌﻨﻬﺞ ﰲ ﺍﻟﺘﺮﻭﻳﺴﺔ .ﻣﺜﺎﻝ :
;)procedure TDate.SetValue (y, m, d: Integer
begin
;end
DateUtils ﺃﻣﺎ ﺷﻔﺮﺓ ﺍﳌﻨﺎﻫﺞ ﻓﻬﻲ ﺑﻐﺎﻳﺔ ﺍﻟﺴﻬﻮﻟﺔ ﻭﳝﻜﻦ ﺍﻹﻋﺘﻤﺎﺩ ﻋﻠﻰ ﺑﻌﺾ ﺗﻌﻠﻴﻤﺎﺕ ﺍﻟﺘﺎﺭﻳﺦ ﺍﳌﻌﺮﻓﺔ ﰲ ﺍﻟﻮﺣﺪﺓ
;)B:= IsInLeapYear(fDate
ﻳﻌﻴﺪ ﻗﻴﻤﺔ ﺑﻮﻟﻴﺎﻧﻴﺔ ﺇﺫﺍ ﻛﺎﻧﺖ ﺍﻟﺴﻨﺔ ﻛﺒﻴﺴﺔ ﺃﻭﻻ
interface
uses ;SysUtils
type
TDate = class
private
;fDate: TDateTime
١٨
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
public
procedure Increase;
end;
implementation
uses
DateUtils;
begin
end;
begin
fDate := NewDate;
end;
begin
end;
١٩
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
procedure TDate.Increase;
begin
fDate := fDate + 1;
end;
begin
// from DateUtils
Result := IsInLeapYear(fDate);
end;
begin
end;
begin
end;
begin
end;
begin
end;
begin
٢٠
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
;end
begin
;end
end.
ﳝﻜﻨﻨﺎ ﺣﺬﻑ ﺍﳉﺰﺀ ﺍﳋﺎﺹ ﺑﺎﻟﻜﻠﻤﺔ ﺍﳌﻔﺘﺎﺣﻴﺔ Writeﻣﻦ ﺗﻌﺮﻳﻒ ﺍﳋﺎﺻﻴﺔ ﻟﻨﺤﺼﻞ ﻋﻠﻰ ﺧﺎﺻﻴﺔ ﻟﻠﻘﺮﺍﺀﺓ ﻓﻘﻂ )(read-only
،ﻭﻋﻨﺪﻫﺎ ﺳﻴﻮﻟﺪ ﺍﳌﺘﺮﺟﻢ ﺧﻄﺄ ﺇﺫﺍ ﺣﺎﻭﻝ ﺍﳌﺴﺘﺨﺪﻡ ﺗﻐﲑ ﻗﻴﻤﺔ ﺧﺎﺻﻴﺔ ﻟﻠﻘﺮﺍﺀﺓ ﻓﻘﻂ .
ﳓﻮﻳﺎ ﳝﻜﻨﻚ ﺣﺬﻑ ﺍﳉﺰﺀ readﻭﺍﳊﺼﻮﻝ ﻋﻠﻰ ﺧﺎﺻﺔ ﻟﻠﻜﺘﺎﺑﺔ ﻓﻘﻂ ﺩﻭﻥ ﺧﻄﺄ ﻣﻦ ﺍﳌﺘﺮﺟﻢ ،ﻭﻟﻜﻦ ﺫﻟﻚ ﻻ ﻳﻌﺘﱪ ﺗﻔﻜﲑﺍ
ﻧﻈﺎﻣﻴﺎ ﻭﻟﻴﺲ ﻟﻪ ﺇﺳﺘﺨﺪﺍﻣﺎﺕ ﺣﻘﻴﻘﻴﺔ .
ﺑﻴﺌﺔ ﺍﻟﺪﻟﻔﻲ ﺗﺘﻌﺎﻣﻞ ﺑﻄﺮﻳﻘﺔ ﺧﺎﺻﻪ ﻣﻊ ﺧﻮﺍﺹ ﺯﻣﻦ-ﺍﻟﺘﺼﻤﻴﻢ ،ﻭﺍﻟﱵ ﺗﻈﻬﺮ ﰲ ﺿﺎﺑﻂ ﺍﻟﻜﺎﺋﻨﺎﺕ ﺃﺛﻨﺎﺀ ﺍﻟﺘﺼﻤﻴﻢ .ﻭﻳﺴﺘﺨﺪﻡ
ﻣﻌﻬﺎ ﳏﺪﺩ ﺍﻟﻮﺻﻮﻝ publishedﺍﻟﺬﻱ ﺳﺘﻌﺮﻑ ﻋﻨﺔ ﰲ ﻗﺴﻢ ﺑﻨﺎﺀ ﺍﻟﻌﻨﺎﺻﺮ ﺍﳉﺪﻳﺪﺓ ﰲ ﻫﺬﺍ ﺍﻟﻜﺘﺎﺏ .
ﺗﺴﻤﻰ ﺍﳋﻮﺍﺹ ﺍﳌﻌﺮﻓﺔ ﺑﺎﶈﺪﺩ Publicﺧﻮﺍﺹ ﺯﻣﻦ-ﺍﻟﺘﻨﻔﻴﺬ ) ، (design-time propertiesﻭﻫﻲ ﳐﺼﺼﺔ ﻟﻺﺳﺘﺨﺪﺍﻡ
ﺿﻤﻦ ﺷﻘﺮﺓ ﺍﻟﱪﻧﺎﻣﺞ .
ﺗﻨﺒﻴﺔ :ﺑﻌﺾ ﺍﻟﺘﻮﺟﻴﻬﺎﺕ ﺍﻹﺿﺎﻓﻴﺔ ﻟﻠﺨﺼﺎﺋﺺ )ﻣﺜﻞ storedﻭ (defaultﺳﻨﺘﻌﺮﺽ ﳍﺎ ﻳﺎﻟﻔﺼﻮﻝ ﺍﻟﻘﺎﺩﻣﺔ .
ﻣﻼﺣﻈﺔ :ﳝﻜﻦ ﻗﺮﺍﺀﺓ ﻗﻴﻤﺔ ﺍﳋﺎﺻﻴﺔ ،ﺃﻭ ﺍﻟﻜﺘﺎﺑﺔ ﺎ ،ﺃﻭ ﺣﱴ ﺇﺳﺘﺨﺪﺍﻣﻬﺎ ﺿﻤﻦ ﺍﻟﺘﻌﺎﺑﲑ ﺍﳌﺨﺘﻠﻔﺔ .ﻭﻟﻜﻦ ﻟﻴﺲ ﻣﻦ
ﺍﻟﻀﺮﻭﺭﻱ ﺃﻥ ﻳﻘﺒﻞ ﲤﺮﻳﺮﻫﺎ ﻛﻤﺘﻐﲑ ﺇﱃ ﻣﻨﻬﺞ ﻣﺎ ،ﻹﺎ ﻟﻴﺴﺖ ﻣﻮﺍﻗﻊ ﺫﺍﻛﺮﺓ ﻣﺜﻞ ﺍﳌﺘﺤﻮﻻﺕ .
٢١
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﺇﺣﺪﻯ ﺍﻷﻓﻜﺎﺭ ﺍﳌﻔﺘﺎﺣﻴﺔ ﻟﻠﺘﻐﻠﻴﻒ ﻫﻲ ﺗﻘﻠﻴﻞ ﺍﳌﺘﻐﲑﺍﺕ ﺍﻟﻌﺎﻣﺔ ﺍﳌﺴﺘﺨﺪﻣﻪ ﻣﻦ ﻛﺎﻣﻞ ﺍﻟﱪﻧﺎﻣﺞ ،ﳝﻜﻦ ﺍﻟﺪﺧﻮﻝ ﺇﱃ ﺍﳌﺘﻐﲑ ﺍﻟﻌﺎﻡ
ﻣﻦ ﺃﻱ ﺟﺰﺀ ﻣﻦ ﺍﻟﱪﻧﺎﻣﺞ ،ﻟﺬﻟﻚ ﻓﺈﻥ ﺗﻐﻴﲑﺍ ﰲ ﻣﺘﺤﻮﻝ ﻋﺎﻡ ﺳﻴﺆﺛﺮ ﻋﻠﻰ ﻛﺎﻣﻞ ﺍﻟﱪﻧﺎﻣﺞ ،ﰲ ﺣﲔ ﺃﻧﻚ ﻋﻨﺪﻣﺎ ﺗﻐﲑ ﲤﺜﻴﻞ
ﺃﺣﺪ ﺣﻘﻮﻝ ﺻﻨﻒ ﻣﺎ ،ﻓﺈﻧﻚ ﲝﺎﺟﺔ ﻟﺘﻐﲑ ﺷﻔﺮﺍﺕ ﺑﻌﺾ ﺍﳌﻨﺎﻫﺞ ﺍﻟﱵ ﺗﺴﺘﺨﺪﻣﺔ ﻓﻘﻂ ،
ﻭﻟﺘﻮﺿﻴﺢ ﻫﺬﺓ ﺍﻟﻔﻜﺮﺓ ﺳﺄﻗﺘﺮﺡ ﻣﺜﺎﻻ ،ﻟﺪﻳﻨﺎ ﺑﺮﻧﺎﻣﺞ ﻟﻪ ﻋﺪﺓ ﺃﺷﻜﺎﻝ ) ، (Multiple Formsﻧﺴﺘﻄﻴﻊ ﺃﻥ ﳒﻌﻞ ﺑﻌﺾ
ﺍﻟﺒﻴﺎﻧﺎﺕ ﻣﺘﺎﺣﺔ ﻟﻜﻞ ﺍﻷﺷﻜﺎﻝ ﺑﺘﻌﺮﻳﻔﻬﺎ ﰲ ﻗﺴﻢ ﺍﻟﻮﺍﺟﻬﺔ ) (Interfaceﻹﺣﺪﻯ ﺍﻷﺷﻜﺎﻝ
var
;Form1: TForm1
;nClicks: Integer
ﺳﻴﻌﻤﻞ ﺍﻟﱪﻧﺎﻣﺞ ﺑﺸﻜﻞ ﺟﻴﺪ ﺬﺓ ﺍﻟﻄﺮﻳﻘﺔ ،ﻭﻟﻜﻦ ﻋﻠﻴﻚ ﺃﻥ ﺗﻌﺮﻑ ﺑﺈﻥ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺍﻟﱵ ﻋﺮﻓﻨﺎﻫﺎ ﻫﻨﺎ ﻟﻴﺴﺖ ﺗﺎﺑﻌﺔ ﻟﻠﺸﻜﻞ
ﺍﻟﺬﻱ ﻋﺮﻓﻨﺎﻫﺎ ﻓﻴﺔ ،ﺑﻞ ﺃﺻﺒﺤﺖ ﺗﺎﺑﻌﺔ ﻟﻜﺎﻣﻞ ﺍﻟﱪﻧﺎﻣﺞ ،ﻓﺈﺫﺍ ﺃﻧﺸﺄﻧﺎ ﺷﻜﻼﻥ ﻣﻦ ﻧﻔﺲ ﺍﻟﺼﻨﻒ ﻓﺈﻤﺎ ﺳﻴﺘﺸﺎﺭﻛﺎﻥ ﺍﻟﺒﻴﺎﻧﺎﺕ
ﺍﳌﻌﺮﻓﺔ ﰲ ﻗﺴﻢ ﺍﻟﻮﺍﺟﻬﺔ ﻧﻔﺴﻬﺎ .ﻣﺜﻼ ﻟﻮ ﻗﻤﻨﺎ ﺑﺈﻧﺸﺎﺀ ﻋﺪﺓ ﻧﺴﺦ ﻣﻦ ﺍﻟﺼﻨﻒ Tform3ﰲ ﺯﻣﻦ ﺍﻟﺘﺸﻐﻴﻞ ﺑﺈﺳﺘﺨﺪﺍﻡ ﺍﻟﺒﺎﱐ ، Create
ﺳﻴﺼﺒﺢ ﻟﺪﻳﻨﺎ ﻋﺪﺓ ﺃﺷﻜﺎﻝ ﻟﻨﻔﺲ ﺍﻟﺼﻨﻒ ،ﻛﻴﻒ ﳒﻌﻞ ﺑﻴﺎﻧﺎﺕ ﻣﺎ ﺧﺎﺻﺔ ﺑﺈﺣﺪﺍﻫﺎ ﻭﻣﺮﺋﻴﺔ ﻣﻦ ﺑﻘﻴﺔ ﺍﻟﱪﻧﺎﻣﺞ ؟
ﻓﺈﺫﺍ ﺃﺭﺩﺕ ﺃﻥ ﻳﻜﻮﻥ ﻟﻜﻞ ﻭﺍﺣﺪ ﻣﻨﻬﻤﺎ ﻧﺴﺨﺘﺔ ﺍﳋﺎﺻﺔ ﻣﻦ ﺍﻟﺒﻴﺎﻧﺎﺕ ،ﻓﻌﻠﻴﻚ ﺇﺿﺎﻓﺔ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺇﱃ ﺻﻨﻒ ﺍﻟﻔﻮﺭﻡ ﻧﻔﺴﺔ
ﻭﺑﺎﻟﺘﺎﱄ ﺳﻴﻨﺴﺦ ﻛﻞ ﺷﻜﻞ ﻧﺴﺨﺔ ﺧﺎﺻﺔ ﺑﻪ .
type
)TForm1 = class(TForm
public
;nClicks: Integer
;end
ﻣﻼﺣﻈﺔ :ﻳﺴﺘﺨﺪﺍﻡ ﺫﻟﻚ ﺑﻜﺜﺮﺓ ﰲ ﺗﻄﺒﻴﻘﺎﺕ MDIﲝﻴﺚ ﳓﺘﺎﺝ ﻣﺘﺤﻮﻻﺕ ﺧﺎﺻﺔ ﺑﻜﻞ ﻓﻮﺭﻡ ﻭﻻ ﻧﻀﻤﻦ ﻣﺎ ﻫﻮ ﻋﺪﺩ
ﺍﻷﺷﻜﺎﻝ ﺍﻟﱵ ﺳﻴﻨﺸﺌﻬﺎ ﺍﳌﺴﺘﺨﺪﻡ ﰲ ﺯﻣﻦ ﺍﻟﺘﺼﻤﻴﻢ ،ﺃﻭ ﰲ ﺗﻄﺒﻴﻘﺎﺕ ﺍﻟﻮﻳﺐ ﻣﺜﻼ ﲝﻴﺚ ﳓﺘﺎﺝ ﺟﻠﺴﺔ ﻟﻜﻞ ﻣﺴﺘﺨﺪﻡ ﻣﻮﺟﻮﺩ
ﺣﺎﻟﻴﺎ ،ﻭﻟﺔ ﺇﺳﺘﺨﺪﺍﻣﺎﺕ ﻛﺜﲑﺓ ﺃﺧﺮﻯ .
٢٢
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﻣﻼﺣﻈﺔ :ﺍﻟﺼﻨﻒ ﺍﻟﺴﺎﺑﻖ ﻳﺴﺘﺨﺪﻡ ﺍﻟﺒﻴﺎﻧﺎﺕ ﻋﻠﻰ ﺃﺎ ﻋﺎﻣﺔ Publicﻭﻣﻦ ﺃﺟﻞ ﺗﻐﻠﻴﻒ ﺟﻴﺪ ﻋﻠﻴﻚ ﺃﻥ ﲡﻌﻞ ﺍﻟﺒﻴﺎﻧﺎﺕ
Privateﻭﺃﻥ ﺗﻀﻴﻒ ﻟﻘﺴﻢ Publicﻣﻨﺎﻫﺞ ﺧﺎﺻﺔ ﻟﻠﻮﺻﻮﻝ ﺇﻟﻴﻬﺎ ،ﻛﻤﺎ ﺗﻌﻠﻤﻨﺎ ﺳﺎﺑﻘﺎ .
ﻭﺑﻴﺒﺴﺎﻃﺔ ﺩﻋﻨﺎ ﻧﻀﻴﻒ ﺧﺎﺻﻴﺔ ﺟﺪﻳﺪﺓ ﺇﱃ ﺻﻨﻒ ﺍﻟﺸﻜﻞ ﻭﻧﺮﻳﺢ ﺑﺎﻟﻨﺎ ﺃﻛﺜﺮ ،ﲝﻴﺚ ﻛﻠﻤﻨﺎ ﺃﺣﺘﺠﻨﺎ ﻟﺘﻐﻴﻴﲑ ﺃﻭ ﻗﺮﺍﺀﺓ ﺍﻟﺒﻴﺎﻧﺎﺕ
ﻣﻦ ﺷﻜﻞ ﺁﺧﺮ ﻧﺴﺘﺨﺪﻡ ﺍﳋﺎﺻﻴﺔ ﻧﻔﺴﻬﺎ ،ﻧﻌﻴﺪ ﻛﺘﺎﺑﺔ ﺍﻟﺘﻌﺮﻳﻒ ﺍﻟﺴﺎﺑﻖ ﻟﻴﺼﺒﺢ ﺑﺎﻟﺸﻜﻞ :
type
)TForm1 = class(TForm
private
;FClicks: Integer
public
;property nClicks: Integer read FClicks write SetClicks
;end
ﺭﺍﺟﻊ ﺍﳌﺜﺎﻝ ﺍﳌﺮﻓﻖ ﻣﻊ ﺍﻷﻣﺜﻠﺔ ،ﻭﻻﺣﻆ ﺃﻧﻨﺎ ﺃﻧﺸﺄﻧﺎ ﻋﺪﺓ ﺃﺷﻜﺎﻝ ﻣﻦ ﻧﻔﺲ ﺍﻟﺼﻨﻒ ﻭﻟﻜﻞ ﻭﺍﺣﺪ ﻣﻨﻬﺎ ﻋﺪﺍﺩ ﻧﻘﺮﺍﺕ ﺧﺎﺹ .
ﻣﻼﺣﻈﺔ :ﺧﺎﺻﻴﺔ ﺯﻣﻦ-ﺍﻟﺘﺸﻐﻴﻞ ﺍﻟﱵ ﺃﺿﻔﻨﺎﻫﺎ ﻟﻦ ﺗﻀﺎﻑ ﺇﱃ ﺿﺎﺑﻂ ﺍﻟﻜﺎﺋﻨﺎﺕ ،ﺑﻞ ﳝﻜﻦ ﺇﺳﺘﺨﺪﺍﻣﻬﺎ ﺩﺍﺧﻞ ﺍﻟﺸﻔﺮﺓ ﻓﻘﻂ.
ﺭﺍﺟﻊ ﺃﻳﻀﺎ :ﻣﺜﺎﻝ ﺍﳌﻘﺎﺭﻧﺔ ﺍﳌﺮﻓﻖ ،ﻟﻠﺘﺄﻛﺪ ﻣﻦ ﺇﺗﻘﺎﻥ ﺍﻟﺘﻌﺎﻣﻞ ﻣﻊ ﻫﺬﺓ ﺍﻟﻔﻜﺮﺓ ﺑﺸﻜﻞ ﺟﻴﺪ ،ﻭﻋﺪﻡ ﺍﻟﻮﻗﻮﻉ ﰲ ﻣﻄﺒﺎﺎ .
ﺍﻟﺒﺎﱐ : Constructor
ﺍﻟﺒﺎﱐ ﻫﻮ ﻣﻨﻬﺞ ﺧﺎﺹ ﻳﺴﺘﺨﺪﻡ ﳊﺠﺰ ﺍﻟﺬﺍﻛﺮﺓ ﳌﻨﺘﺴﺦ ﻣﻦ ﺻﻨﻒ ﻟﻴﺼﺒﺢ ﺟﺎﻫﺰﺍﹰ ﻟﻺﺳﺘﺨﺪﺍﻡ ،ﻭﻛﻨﺎ ﻗﺪ ﲰﻴﻨﺎﻩ ﺍﳌﻨﻬﺞ
Createﰲ ﻣﺎﻣﻀﻰ ،ﺍﳊﻘﻴﻘﺔ ﺍﻟﱵ ﺃﺭﻳﺪﻙ ﺃﻥ ﺗﻌﺮﻓﻬﺎ ﻋﻦ ﺍﻟﺒﺎﱐ ﺃﻧﺔ ﻳﻌﻴﺪ ﺍﻟﻐﺮﺽ ﻛﻘﻴﻤﺔ ﺟﺎﻫﺰﺓ ﻟﻺﺳﺘﺨﺪﺍﻡ ﺣﻴﺚ ﻧﺴﺘﻄﻴﻊ
ﻧﺴﻴﺔ ﺇﱃ ﻣﺘﺤﻮﻝ ﻣﻮﺟﻮﺩ ﻟﻜﻲ ﻧﺴﺘﺨﺪﻣﺔ ﻻﺣﻘﺎ .ﺃﻱ ﻛﺄﻧﺔ ﺗﺎﺑﻊ ﻗﻴﻤﺘﺔ ﺍﳌﻌﺎﺩﺓ ﻫﻲ ﺍﻟﻐﺮﺽ ﻧﻔﺴﺔ ،ﻣﺜﻼ :
;var B:Tbutton
begin
;)B:=TButton.Create(Application
ﺃﺟﻞ ﺍﻟﺼﻨﻒ Tbutton ﻻﺣﻆ ﺃﻥ ﺍﻟﺒﺎﱐ ﻳﺴﺘﺨﺪﻡ ﻣﻊ ﺍﻟﺼﻨﻒ ﻟﻜﻲ ﻳﻌﻴﺪ ﺍﻟﻐﺮﺽ ،ﻣﺜﻼ ﻫﻨﺎ ﺃﺳﺘﺪﻋﻴﻨﺎ ﺍﻟﺒﺎﱐ ﻣﻦ
ﻭﺍﻟﻨﺘﻴﺠﺔ ﻧﻀﻌﻬﺎ ﺑﺎﳌﺘﺤﻮﻝ ، Bﻭﻧﺴﺘﻄﻴﻊ ﺇﺳﺘﺨﺪﺍﻡ Bﻻﺣﻘﺎ ﻟﻠﺘﻌﺎﻣﻞ ﻣﻊ ﺍﻟﻐﺮﺽ ﺍﻟﻨﺎﺗﺞ ﻛﻤﺎ ﻧﺘﻌﺎﻣﻞ ﻣﻊ ﺃﻱ ﺯﺭ .
٢٣
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
begin
;)b:=TButton.Create(Application
;b.Parent:=form1
;b.Left:=10
;b.Top:=10
;'b.Caption:='Hi
;end
ﺇﻥ ﺑﻴﺎﻧﺎﺕ ﺃﻱ ﻏﺮﺽ ﺟﺪﻳﺪ ﺗﻜﻮﻥ ﻣﻀﺒﻮﻃﺔ ﻟﻠﺼﻔﺮ ،ﻓﺈﺫﺍ ﺃﺭﺩﺕ ﺃﻥ ﺗﺒﺪﺃ ﻫﺬﺓ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺑﻘﻴﻢ ﳏﺪﺩﺓ ﻋﻠﻴﻚ ﻛﺘﺎﺑﺔ ﺑﺎﱐ ﺟﺪﻳﺪ
ﳍﺎ ﲢﺪﺩ ﻓﻴﺔ ﺍﻟﻘﻴﻢ ﺍﻹﻓﺘﺮﺍﺿﻴﺔ ﺍﻟﱵ ﻳﺒﺪﺃ ﺍﻟﻐﺮﺽ ﺎ ،
ﻟﺒﻨﺎﺀ ﺑﺎﱐ ﺟﺪﻳﺪ ﻧﺴﺘﺨﺪﻡ ﺍﻟﻜﻠﻤﺔ ﺍﳌﻔﺘﺎﺣﻴﺔ constructorﰲ ﺑﺪﺍﻳﺔ ﺗﻌﺮﻳﻒ ﻣﻨﻬﺠﻨﺎ ﺍﳉﺪﻳﺪ )ﺑﺪﻻ ﻣﻦ Functionﺃﻭ
. (Procedureﰲ ﺍﳊﻘﻴﻘﺔ ﺗﺴﺘﻄﻴﻊ ﺃﻥ ﺗﺴﺘﺨﺪﻡ ﺃﻱ ﺇﺳﻢ ﳍﺬﺍ ﺍﻟﺒﺎﱐ ﻭﻟﻦ ﻳﻌﻄﻴﻚ ﺍﳌﺘﺮﺟﻢ ﺃﻱ ﺧﻄﺄ ﳓﻮﻱ ،ﻭﻟﻜﻦ ﺇﺫﺍ ﺃﺭﺩﺕ
ﺭﺃﻳﻲ ﻻﺗﺴﺘﺨﺪﻡ ﺃﺑﺪﺍ ﺇﺳﻢ ﻏﲑ ﺍﻹﺳﻢ ﺍﻟﻘﻴﺎﺳﻲ ﻟﻪ ،ﻭﺍﻟﺬﻱ ﺃﺻﺒﺤﺖ ﺗﻌﺮﻓﺔ ﺟﻴﺪﺍ ﻭﻫﻮ " . "Createﻹﻥ ﺃﻱ ﻣﱪﻣﺞ ﺁﺧﺮ ﻟﻦ
ﻳﺘﻌﺮﻑ ﻋﻠﻰ ﺍﻟﺒﺎﱐ ﺍﳋﺎﺹ ﺑﻚ ﻭﳛﺴﻦ ﺇﺳﺘﺨﺪﺍﻣﺔ ،،ﺗﺬﻛﺮ ﳓﻦ ﻫﻨﺎ ﻟﻨﺘﻌﻠﻢ ﻛﺘﺎﺑﺔ ﺑﺮﺍﻣﺞ ﻗﻴﺎﺳﻴﺔ ﻛﻤﺎ ﻳﻜﺘﺒﻬﺎ ﺍﳋﱪﺍﺀ
ﻭﺍﶈﺘﺮﻓﻮﻥ .
ﻣﻼﺣﻈﺔ :ﻋﻨﺪﻣﺎ ﺗﻌﺮﻑ ﺑﺎﱐ ﺟﺪﻳﺪ ﻟﺼﻨﻒ ﻣﻮﺟﻮﺩ ﺃﻭ ﻟﺼﻨﻒ ﻣﺴﺘﻖ ،ﻓﺈﻥ ﺍﻟﺒﺎﱐ ﺍﻟﻘﺪﱘ ﻟﻦ ﻳﺼﺒﺢ ﻣﺘﺎﺣﺎ ﻭﺳﻴﺼﺒﺢ
ﺇﺳﺘﺨﺪﺍﻡ ﺍﻟﺒﺎﱐ ﺍﳉﺪﻳﺪ ﺇﻟﺰﺍﻣﻴﺎ ،ﻭﻟﻠﺘﻐﻠﺐ ﻋﻠﻰ ﻫﺬﺓ ﺍﳊﺎﻟﺔ ﻭﺇﺑﻘﺎﺀ ﺍﻟﺒﺎﱐ ﺍﻷﺳﺎﺳﻲ ﻣﺘﺎﺣﺎ ﺑﺎﻹﺿﺎﻓﺔ ﺇﱃ ﺍﻟﺒﺎﱐ ﺍﳉﺪﻳﺪ ﻋﻠﻴﻚ
ﺇﺳﺘﺨﺪﺍﻡ ﻣﻴﺰﺓ ﺍﻟﺘﺤﻤﻴﻞ ﺍﻟﺰﺍﺋﺪ ﻷﲰﺎﺀ ﺍﳌﻨﺎﻫﺞ ﻭﺍﻟﱵ ﺳﺒﻖ ﺫﻛﺮﻫﺎ .ﻣﺜﺎﻝ :
type
TDate = class
public
;constructor Create; overload // the old constructor
;constructor Create (y, m, d: Integer); overload // the new constructor
ﺣﻴﺚ ﻧﺴﺘﻄﻴﻊ ﺿﺒﻂ ﻗﻴﻤﺔ ﺍﻟﺘﺎﺭﻳﺦ ﻋﻨﺪ ﺍﻹﻧﺸﺎﺀ ﰲ ﺍﳊﺎﻟﺔ ﺍﻟﺜﺎﻧﻴﺔ ،ﺃﻣﺎ ﺍﳊﺎﻟﺔ ﺍﻷﻭﱃ ﺳﺘﺄﺧﺬ ﻗﻴﻤﺔ ﺍﻟﺘﺎﺭﻳﺦ ﺍﻹﻓﺘﺮﺍﺿﻲ )ﺃﻭ
ﺍﳊﺎﱄ ﻣﺜﻼ ( .
٢٤
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﲡﺮﺑﺔ :
ﺇﺫﺍ ﱂ ﻧﺴﺘﺨﺪﻡ ﺍﻟﺘﺤﻤﻴﻞ ﺍﻟﺰﺍﺋﺪ ﻓﺈﻥ ﺍﻟﺒﺎﱐ ﺍﳉﺪﻳﺪ ﺳﻴﺤﻞ ﲤﺎﻣﺎ ﳏﻞ ﺍﻟﺒﺎﱐ ﺍﻟﻘﺪﱘ ،ﻭﻟﻦ ﻳﺼﺒﺢ ﺑﺎﻹﻣﻜﺎﻥ ﺇﺳﺘﺨﺪﺍﻡ ﺍﻟﺒﺎﱐ ﺍﻟﻘﺪﱘ
،ﻣﺜﻼ ﺟﺮﺏ ﺍﻟﺸﻔﺮﺓ ﺍﻟﺘﺎﻟﻴﺔ ﻭﻻﺣﻆ ﺍﳋﻄﺄ ﺍﻟﻨﺎﺗﺞ ﻋﻨﺪ ﳏﺎﻭﻟﺔ ﺇﺳﺘﺪﻋﺎﺀ ﺍﻟﺒﺎﱐ ﺍﻷﺻﻠﻲ :
type
TDate = class
public
;)constructor Create (y, m, d: Integer
…..
var
;ADay: TDate
begin
// Error, does not compile:
;ADay := TDate.Create
// This one is OK:
;)ADay := TDate.Create (1, 1, 2000
ﻣﻼﺣﻈﺔ ﻣﻬﻤﺔ :ﺇﻥ ﻗﻮﺍﻋﺪ ﻛﺘﺎﺑﺔ ﺍﻟﺒﺎﱐ ﻣﻦ ﺃﺟﻞ ﻋﻨﺎﺻﺮ ﺟﺪﻳﺪﺓ ﲣﺘﻠﻒ ﻗﻠﻴﻼ ﻛﻤﺎ ﺳﺘﻼﺣﻆ ﰲ ﺍﻟﻘﺴﻢ ﺍﳋﺎﺹ ﺑﺒﻨﺎﺀ ﻋﻨﺎﺻﺮ
ﺟﺪﻳﺪﺓ .ﺣﻴﺚ ﺳﺘﻼﺣﻆ ﺇﺳﺘﺨﺪﺍﻡ ﺍﻟﺒﺎﱐ ﺍﻟﻘﺪﱘ ﺿﻤﻦ ﺍﻟﺒﺎﱐ ﺍﳉﺪﻳﺪ ﺑﻌﻤﻠﻴﺔ " . " override
ﺑﻨﻔﺲ ﺍﻟﻄﺮﻳﻘﺔ ،ﺑﺎﻹﺿﺎﻓﺔ ﺇﱃ ﺇﻣﻜﺎﻧﻴﺔ ﻛﺘﺎﺑﺔ ﺑﺎﱐ ﺧﺎﺹ ﻟﻠﺼﻨﻒ ،ﳝﻜﻦ ﻛﺬﻟﻚ ﻛﺘﺎﺑﺔ ﻫﺎﺩﻡ ﺧﺎﺹ ﻟﺔ .ﻭﻳﻘﻮﻡ ﺑﺎﻟﻌﻤﻞ
ﺍﳌﻌﺎﻛﺲ ﺣﻴﺚ ﳛﺮﺭ ﺃﻱ ﺫﺍﻛﺮﺓ ﻗﺎﻡ ﺍﻟﺒﺎﱐ ﲝﺠﺰﻫﺎ ﻭﱂ ﲢﺮﺭ ﻓﻴﻤﺎ ﺑﻌﺪ .ﻭﻳﺒﺪﺃ ﺑﺎﻟﻜﻠﻤﺔ ﺍﳌﻔﺘﺎﺣﻴﺔ destructorﻭ ﻳﻜﻮﻥ ﺇﲰﺔ
. Destroy
ﺳﺘﺮﻯ ﻻﺣﻘﺎ ﺇﻣﻜﺎﻧﻴﺔ ﺇﺳﺘﺨﺪﺍﻡ ﺍﳍﺎﺩﻡ ﺍﻟﻘﺪﱘ ﺿﻤﻦ ﺍﳉﺪﻳﺪ ﻣﻦ ﺃﺟﻞ ﺃﻥ ﻳﻘﻮﻡ ﺍﻟﺼﻨﻒ ﺑﺒﻌﺾ ﻋﻤﻠﻴﺎﺕ ﺍﻟﺘﻨﻈﻴﻒ ﺩﻭﻥ ﺃﻥ
ﻧﺸﻐﻞ ﺑﺎﻟﻨﺎ ﻓﻴﻬﺎ ﻣﻦ ﺟﺪﻳﺪ .
ﻻ ﺗﺴﺘﺨﺪﻡ ﺃﺑﺪﺍ ﺇﺳﻢ ﻟﻠﻬﺎﺩﻡ ﻏﲑ ﺍﻹﺳﻢ ، Destroyﻹﻥ ﺍﻷﻏﺮﺍﺽ ﻳﺘﻢ ﲢﺮﻳﺮﻫﺎ ﻋﺎﺩﺓ ﺑﺎﳌﻨﻬﺞ ﺍﻟﺸﻬﲑ Freeﻭﻣﺒﺪﺃ ﻫﺬﺍ
ﺍﳌﻨﻬﺞ) :(Freeﻫﻮ ﺇﺧﺘﺒﺎﺭ ﺇﺫﺍ ﻛﺎﻧﺖ ﻗﻴﻤﺔ ﺍﻟﻐﺮﺽ Nilﻗﺒﻞ ﺃﻥ ﻳﺴﺘﺪﻋﻲ ﺍﳌﻨﻬﺞ ﺍﳍﺎﺩﻡ ، Destroyﻭﺑﺎﻟﺘﺎﱄ ﻓﺈﻥ Freeﻟﻦ
ﻳﺘﻌﺮﻑ ﻋﻠﻰ ﺍﳍﺎﺩﻡ ﺍﳉﺪﻳﺪ ﺍﻟﺬﻱ ﻗﻤﻨﺎ ﺑﺒﻨﺎﺀﺓ ﺇﺫﺍ ﱂ ﻳﻜﻦ ﺇﲰﺔ Destroyﻭﺳﺘﻨﺘﺞ ﺃﺧﻄﺎﺀ .
ﺇﻥ Freeﻫﻲ ﻣﻨﻬﺞ ﻟﻠﺼﻨﻒ ﺍﻷﺏ Tobjectﻭﺍﻟﺬﻱ ﺗﺮﺛﺔ ﻛﻞ ﺍﻷﻏﺮﺍﺽ ﺍﻷﺧﺮﻯ .
٢٥
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﻭﺍﳉﺪﻳﺮ ﺑﺎﻟﺬﻛﺮ ﻫﻨﺎ ﺃﻥ Freeﻟﻦ ﺗﻘﻮﻡ ﺑﻀﺒﻂ ﻗﻴﻤﺔ ﺍﻟﻐﺮﺽ ﺇﱃ Nilﺑﻌﺪ ﲢﺮﻳﺮ ﺍﻟﺬﺍﻛﺮﺓ ﺍﳋﺎﺻﺔ ﺑﻪ .ﻟﺬﻟﻚ ﻋﻠﻴﻚ ﺃﻥ ﺗﻘﻮﻡ
ﺑﺬﻟﻚ ﺑﻨﻔﺴﻚ ﻭﺍﻟﺴﺒﺐ ﺑﺴﻴﻂ ﺃﻥ ﺍﻟﻐﺮﺽ ﻟﻦ ﻳﻌﺮﻑ ﻣﺎ ﻫﻲ ﺍﳌﺘﺤﻮﻻﺕ ﺍﻟﱵ ﻧﺴﺒﺖ ﺇﻟﻴﺔ ،ﻭﻟﻦ ﻳﺴﺘﻄﻴﻊ ﺍﻟﺘﺄﻛﺪ ﻣﻦ ﺃﻧﻪ ﺿﺒﻂ
ﻗﻴﻤﺔ ﲨﻴﻊ ﻫﺬﺓ ﺍﳌﺘﺤﻮﻻﺕ ﺇﱃ ، Nilﻟﺬﻟﻚ ﺗﺮﻛﺖ ﺍﻟﻌﻤﻠﻴﺔ ﺇﱃ ﺍﳌﺴﺘﺨﺪﻡ ،ﻭﻟﻜﻦ ﺩﻟﻔﻲ ﲤﻠﻚ ﺑﻌﺾ ﺍﻟﺪﻭﺍﻝ ﺍﳌﺴﺎﻋﺪﺓ ﻫﻨﺎ
ﻣﺜﻞ ﺍﻟﺪﺍﻟﺔ FreeAndNilﺍﻟﱵ ﻗﺪ ﺗﺴﺎﻋﺪ ﺃﺣﻴﺎﻧﺎ .ﺣﻴﺚ ﺃﺎ ﲢﺮﺭ ﺍﻟﻐﺮﺽ ﻭﺗﻠﻐﻲ ﺍﳌﺮﺟﻊ ﺍﻟﺬﻱ ﻳﺸﲑ ﺇﻟﻴﺔ )ﻳﺼﺒﺢ ﺍﳌﺆﺷﺮ
ﻣﻌﺮﻓﺎ ﻣﺜﻞ ﺃﻱ ﻣﺘﺤﻮﻝ ﻭﻟﻜﻨﺔ ﻻﻳﺸﲑ ﺇﱃ ﺃﻱ ﻗﻴﻤﺔ ﺑﺎﻟﺬﺍﻛﺮﺓ ( .ﻋﻠﻰ ﻛﻞ ﺣﺎﻝ ﺗﺴﺘﻄﻴﻊ ﺍﻟﻘﻴﺎﻡ ﺑﺬﻟﻚ ﻳﺪﻭﻳﺎ ﺑﺈﺳﺘﺨﺪﺍﻡ
ﺍﻟﺴﻄﺮﻳﻦ ﺍﻟﺘﺎﻟﻴﲔ :
;Obj1.Free
;Obj1 := nil
ﺇﻥ ﺗﻌﺮﻳﻒ ﻣﺘﻐﻴﲑ ﻣﻦ ﺻﻨﻒ ﻣﺎ ،ﰲ ﺑﻌﺾ ﺍﻟﻠﻐﺎﺕ ﺍﻟﻐﺮﺿﻴﺔ ﺍﻟﺘﻮﺟﺔ ﺍﻷﺧﺮﻯ ،ﺳﻴﻨﺸﻲﺀ ﻣﻨﺘﺴﺨﺎ ﻣﻦ ﻫﺬﺍ ﺍﻟﺼﻨﻒ ﺗﻠﻘﺎﺋﻴﺎ .
ﻭﻟﻜﻦ ﺩﻟﻔﻲ ﻣﺒﻨﻴﺔ ﻋﻠﻰ ﳕﻮﺫﺝ ﻣﺮﺟﻌﻴﺔ ﺍﻟﻐﺮﺽ ﺑﺪﻻ ﻣﻦ ﺫﻟﻚ ،ﻭﺍﻟﻔﻜﺮﺓ ﰲ ﺫﻟﻚ ﺃﻥ ﺗﻌﺮﻳﻒ ﻣﺘﻐﲑ ﰲ ﺩﻟﻔﻲ ﻣﻦ ﳕﻂ ﺻﻨﻒ
ﻣﺎ ﻟﻦ ﳜﺰﻥ ﺍﻟﻐﺮﺽ ﺩﺍﺧﻠﺔ ،ﻭﻟﻜﻨﺔ ﳜﺰﻥ ﻣﺮﺟﻊ ﳌﻮﻗﻊ ﺍﻟﻐﺮﺽ ﰲ ﺍﻟﺬﺍﻛﺮﺓ ،ﺃﻱ ﻋﺒﺎﺭﺓ ﻋﻦ ﻣﺆﺷﺮ ) (Pointerﻳﺸﲑ ﺇﱃ ﻣﻮﻗﻊ
ﺧﺎﺹ ﺑﺎﻟﺬﺍﻛﺮﺓ ﺣﻴﺚ ﻳﺘﻢ ﲣﺰﻳﻦ ﺟﺴﻢ ﺍﻟﻐﺮﺽ ﻫﻨﺎﻙ ،ﻭﻟﻴﺲ ﺿﻤﻦ ﺍﳌﺘﻐﲑ ﻧﻔﺴﺔ ،ﻭﺑﻨﺎﺀ ﻋﻠﻰ ﺫﻟﻚ ﻛﻤﺎ ﻻﺣﻈﺖ ﻣﻌﻲ ﰲ
ﺍﻟﺼﻔﺤﺎﺕ ﺍﻟﺴﺎﺑﻘﺔ ﺇﻥ ﺗﻌﺮﻳﻒ ﻣﺘﻐﲑ ﻻﻳﻌﲏ ﺇﻧﺸﺎﺀ ﺍﻟﻐﺮﺽ ﰲ ﺍﻟﺬﺍﻛﺮﺓ )ﳑﺎ ﻳﺮﺑﻚ ﻣﺴﺘﺨﺪﻣﻲ ﺩﻟﻔﻲ ﺍﳉﺪﺩ( ،ﻭﻟﻜﻨﻚ ﺗﻜﻮﻥ
ﺣﺠﺰﺕ ﻣﻮﻗﻊ ﺫﺍﻛﺮﺓ ﺻﻐﲑ ﳛﻮﻱ ﻋﻨﻮﺍﻥ ﻣﻮﻗﻊ ﺍﻟﺬﺍﻛﺮﺓ ﺍﻵﺧﺮ ﺍﻟﺬﻱ ﳜﺰﻥ ﺍﻟﻐﺮﺽ . ،ﻭﺍﻷﺻﻨﺎﻑ ﺍﻟﱵ ﻧﻌﺮﻓﻬﺎ ﻳﺪﻭﻳﺎ ﲢﺘﺎﺝ
ﺇﱃ ﺇﻧﺸﺎﺀ ﻳﺪﻭﻱ )ﺍﳌﻨﻬﺞ ، (Createﺃﻣﺎ ﺍﻟﻌﻨﺎﺻﺮ ﺍﻟﱵ ﺗﻀﻌﻬﺎ ﻋﻠﻰ ﺍﻟﺸﻜﻞ ) (Formﺳﺘﻘﻮﻡ ﺩﻟﻔﻲ ﺑﺈﻧﺸﺎﺋﻬﺎ ﺁﻟﻴﺎ .
ﻭﺑﺎﻟﻄﺒﻊ ﲢﺘﺎﺝ ﺇﱃ ﲢﺮﻳﺮ ﺍﻷﻏﺮﺍﺽ ﺍﻟﱵ ﺇﻧﺘﻬﻴﺖ ﻣﻦ ﺇﺳﺘﺨﺪﺍﻣﻬﺎ ،ﻹﺎ ﺃﺻﺒﺤﺖ ﺗﺸﻐﻞ ﺫﺍﻛﺮﺓ ﻏﲑ ﻣﻔﻴﺪﺓ .
ﻃﺎﳌﺎ ﺗﻘﻮﻡ ﺑﺈﻧﺸﺎﺀ ﺍﻷﻏﺮﺍﺽ ﻭﲢﺮﻳﺮﻫﺎ ﻋﻨﺪ ﺍﻹﻧﺘﻬﺎﺀ ﻓﺈﻥ ﳕﻮﺫﺝ ﻣﺮﺟﻌﻴﺔ ﺍﻟﻐﺮﺽ ﻳﻌﻤﻞ ﺑﺪﻭﻥ ﺃﺩﱏ ﻣﺸﻜﻠﺔ ﻭﻳﻌﺘﱪ ﻣﺘﻤﺎﺳﻜﺎ
ﺟﺪﺍ ،ﺃﻣﺎ ﺍﳋﱪ ﺍﻟﺴﻌﻴﺪ ﺍﻵﻥ ﺃﻧﺔ ﳝﻠﻚ ﺃﳘﻴﺔ ﺧﺎﺻﺔ ﻭﻗﺪﺭﺓ ﻋﺎﻟﻴﺔ ﻋﻠﻰ ﺇﺩﺍﺭﺓ ﺍﻟﺬﺍﻛﺮﺓ ﻭﻟﺔ ﺍﻟﻜﺜﲑ ﻣﻦ ﺍﻟﻔﻮﺍﺋﺪ ،ﻭﺃﻟﻴﻚ ﺑﻌﻀـﺎﹰ
ﻣﻦ ﺫﻟﻚ :
ﲟﺎ ﺃﻥ ﺍﳌﺘﻐﲑ ﺍﻟﺬﻱ ﳛﻮﻱ ﺍﻟﻐﺮﺽ ﻳﺪﻝ ﻓﻘﻂ ﻋﻠﻰ ﺍﻟﻌﻨﻮﺍﻥ ﺍﻷﺳﺎﺳﻲ ﻟﻠﻐﺮﺽ ﰲ ﺍﻟﺬﺍﻛﺮﺓ ،ﻓﺈﻧﻨﺎ ﻧﺴﺘﻄﻴﻊ ﺗﻌﺮﻳﻒ ﺃﻛﺜﺮ ﻣﻦ
ﻣﺘﺤﻮﻝ ﺗﺪﻝ ﲨﻴﻌﻬﺎ ﻋﻠﻰ ﺍﻟﻐﺮﺽ ﻧﻔﺴﻪ ،ﻓﺈﺫﺍ ﻗﻤﻨﺎ ﺑﻨﺴﺐ ﻣﺘﺤﻮﻝ ﺟﺪﻳﺪ ﻣﺎ ﻣﻦ ﻧﻔﺲ ﺍﻟﺼﻨﻒ ﺇﱃ ﺁﺧﺮ ﲤﺖ ﻴﺌﺘﺔ ﻓﺈﻧﻨﺎ
ﻧﺴﺘﻄﻴﻊ ﺍﻟﺘﻌﺎﻣﻞ ﻣﻊ ﺍﳌﺘﺤﻮﻝ ﺍﳉﺪﻳﺪ ﺩﻭﻥ ﺃﺩﱏ ﻣﺸﻜﻠﺔ .
٢٦
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﻣﺜﺎﻝ :
;)procedure Tform1.Button1Click(Sender: TObject
var
;NewDay: TDate
begin
;NewDay := TDate.Create
;TheDay := NewDay
;Label1.Caption := TheDay.GetText
;end
ﻣﺎﺫﺍ ﺣﺼﻞ ...؟ ﻳﻘﻮﻡ ﻫﺬﺍ ﺍﻟﻜﻮﺩ ﺑﻨﺴﺦ ﻣﻮﻗﻊ ﺫﺍﻛﺮﺓ ﺍﻟﻐﺮﺽ ﺍﻟﺬﻱ ﻳﺸﲑ ﺇﻟﻴﺔ ﺍﳌﺘﺤﻮﻝ NewDayﻭﻭﺿﻌﺔ ﰲ ﺍﳌﺘﺤﻮﻝ
، TheDayﺇﻥ ﺫﻟﻚ ﻟﻴﺲ ﻧﺴﺦ ﺑﻴﺎﻧﺎﺕ ﻏﺮﺽ ﻣﺎ ﺇﱃ ﻏﺮﺽ ﺁﺧﺮ ،ﺇﻥ ﻫﺬﺓ ﺍﻟﻌﻤﻠﻴﺔ ﺳﻬﻠﺔ ﻭﺳﺮﻳﻌﺔ ﺍﻟﺘﻨﻔﻴﺬ ﻹﺎ ﺗﻨﻘﻞ ﻋﻨﺎﻭﻳﻦ
ﻣﻮﺍﻗﻊ ﺍﻟﺬﺍﻛﺮﺓ ﻓﻘﻂ .
ﻭﻟﻜﻦ ﻋﻠﻴﻚ ﺃﻥ ﲢﺬﺭ ﻣﻦ ﺫﻟﻚ ،ﻭﲢﺴﻦ ﺇﺳﺘﺨﺪﺍﻣﺔ ،ﻻﺣﻆ ﺃﻧﻨﺎ ﺳﻨﻘﻮﻡ ﺑﺈﻧﺸﺎﺀ ﺍﻟﻐﺮﺽ ﻣﻦ ﺟﺪﻳﺪ ﻛﻞ ﻣﺮﺓ ﻳﺘﻢ ﺍﻟﻀﻐﻂ
ﻋﻠﻰ ﺍﻟﺰﺭ button1ﻭﱂ ﻧﻘﻢ ﺑﺘﺤﺮﻳﺮﺓ ﺑﺈﺳﺘﺨﺪﺍﻡ Freeﻣﺜﻼ ،
ﻭﻟﺘﺠﻨﺐ ﺫﻟﻚ ﺗﺴﺘﻄﻴﻊ ﺑﺒﺴﺎﻃﺔ ﲢﺮﻳﺮ ﺍﻟﻐﺮﺽ ﺍﻟﻘﺪﱘ ﻗﺒﻞ ﺑﻨﺎﺀ ﺍﻟﻐﺮﺽ ﺍﳉﺪﻳﺪ :
;)procedure TDateForm.BtnTodayClick(Sender: TObject
begin
;TheDay.Free
;TheDay := TDate.Create
ﺇﻥ ﻫﺬﺓ ﺍﳌﻴﺰﺓ ﺗﺒﺪﻭ ﻣﻴﺰﺓ ﻋﺎﺩﻳﺔ ﺑﺪﺍﻳﺔ ﻭﻟﻜﻦ ﻋﻠﻴﻚ ﺃﻥ ﺗﻌﺮﻑ ﺃﻥ ﳍﺎ ﺗﻄﺒﻴﻘﺎﺕ ﻣﻬﻤﺔ ،ﺇﻥ ﺇﻣﻜﺎﻧﻴﺔ ﺗﻌﺮﻳﻒ ﻣﺘﺤﻮﻝ ﺟﺪﻳﺪ
ﳝﻜﻨﺔ ﺃﻥ ﻳﺸﲑ ﺇﱃ ﻏﺮﺽ ﻣﺎ ﳚﻌﻞ ﻣﻦ ﺍﳌﻤﻜﻦ ﺇﺳﺘﺨﺪﺍﻡ ﺍﳌﺘﺤﻮﻝ ﻟﺘﺨﺰﻳﻦ ﺍﻟﻐﺮﺽ ﺍﻟﻨﺎﺗﺞ ﻣﻦ ﻗﺮﺍﺀﺓ ﺇﺣﺪﻯ ﺍﳋﺼﺎﺋﺺ ،
ﻭﺇﺳﺘﺨﺪﺍﻣﻪ ﻓﻴﻤﺎ ﺑﻌﺪ ،ﻣﺜﻼ :
var
;ADay: TDate
begin
;ADay := UserInformation.GetBirthDate
// use a ADay
ﺇﻧﻨﺎ ﻧﻜﺴﺐ ﺩﻳﻨﺎﻣﻴﻜﻴﺔ ﺧﺎﺻﺔ ﻟﻠﺘﻌﺎﻣﻞ ﻣﻊ ﺍﻷﻏﺮﺍﺽ ﻭﻧﺴﺘﻄﻴﻊ ﺗﺸﺒﻴﺔ ﺫﻟﻚ ﺑﺄﻱ ﻣﺘﺤﻮﻝ ﻋﺎﺩﻱ .
ﻛﻤﺎ ﺗﺴﺘﻄﻴﻊ ﲤﺮﻳﺮ ﺍﻟﻐﺮﺽ ﺬﺓ ﺍﻟﻄﺮﻳﻘﺔ ﻋﻠﻰ ﺷﻜﻞ ﺑﺎﺭﺍﻣﺘﺮ ﺧﺎﺹ ﺑﺘﺎﺑﻊ ﻣﺎ ،ﺃﻱ ﺃﻧﻨﺎ ﻧﻌﺎﻣﻞ ﺍﻟﻐﺮﺽ ﻛﻤﺘﺤﻮﻝ ﻭﳕﺮﺭﺓ ﺇﱃ
ﻣﻨﺎﻫﺞ ﺗﻘﻮﻡ ﲟﻌﺎﳉﺘﺔ ﻭﺍﻟﺘﻌﺪﻳﻞ ﻓﻴﺔ ﻣﻦ ﻣﻜﺎﻧﺔ .
ﻣﺜﻼ ﻧﻔﺮﺽ ﺇﺟﺮﺍﺋﻴﺔ ﳍﺎ ﺑﺎﺭﺍﻣﺘﺮ ﻭﺣﻴﺪ ﻣﻦ ﺍﻟﺼﻨﻒ ، TButtonﳕﺮﺭ ﳍﺎ ﺯﺭ ﻣﺎ ﻓﺘﻘﻮﻡ ﺑﺘﻐﻴﲑ ﺇﲰﺔ ﻣﺜﻼ ﺃﻭ ﺃﻱ ﺑﻴﺎﻧﺎﺕ ﳝﻠﻜﻬﺎ :
;)procedure ChangeCaption (B: TButton
begin
;'B.Caption := B.Caption + ' was Modified
;end
…………
// call...
)ChangeCaption (Button1
٢٧
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﺍﳌﺘﺤﻮﻝ ﺍﻟﺬﻱ ﻗﻤﻨﺎ ﺑﺘﻤﺮﻳﺮﺓ ﻛﺰﺭ ﺃﻋﻄﻰ ﻋﻨﻮﺍﻥ ﺍﻟﺬﺍﻛﺮﺓ ﻟﻺﺟﺮﺍﺋﻴﺔ ﺍﻟﱵ ﺩﺧﻠﺖ ﺇﻟﻴﺔ ﻭﻗﺎﻣﺖ ﺑﺎﻟﺘﻌﺎﻣﻞ ﻣﻌﻪ ﻣﺒﺎﺷﺮﺓ .،
ﻫﺬﺍ ﻳﻌﲏ ﺃﻥ ﺍﻟﻐﺮﺽ ﰎ ﲤﺮﻳﺮﺓ ﺑﺎﳌﺮﺟﻊ ﺑﻼ ﺇﺳﺘﺨﺪﺍﻡ ﺍﻟﻜﻠﻤﺔ ﺍﳌﻔﺘﺎﺣﻴﺔ Varﺍﻟﱵ ﻧﺴﺘﺨﺪﻣﻬﺎ ﺑﺎﳊﺎﻟﺔ ﺍﻟﻌﺎﺩﻳﺔ ،ﻭﺑﺪﻭﻥ ﺃﻱ ﻣﻦ
ﺍﻟﺘﻘﻴﻴﺪﺍﺕ ﺍﻷﺧﺮﻯ ﺍﻟﱵ ﺗﻔﺮﺿﻬﺎ ﺣﺎﻟﺔ ﺍﻟﺘﻤﺮﻳﺮ ﺑﺎﳌﺮﺟﻊ ). (pass-by-reference
ﻟﻜﻦ ﻣﺎﺫﺍ ﻟﻮﻛﻨﺎ ﻧﺮﻳﺪ ﺃﻥ ﻧﻘﻮﻡ ﺑﻨﺴﺦ ﺍﻟﺒﻴﺎﻧﺎﺕ ﻓﻌﻠﻴﺎ ﻣﻦ ﻏﺮﺽ ﺇﱃ ﺁﺧﺮ ،ﻫﺬﺓ ﺍﳌﺮﺓ ﻻﻧﺮﻳﺪ ﺍﻟﺘﻌﺎﻣﻞ ﻣﻊ ﻣﺘﻐﲑﺍﺕ ﻭﻋﻨﺎﻭﻳﻦ ،
ﻹﻧﻨﺎ ﻧﺮﻳﺪ ﻧﺴﺦ ﻓﻌﻠﻲ ﻟﻠﻐﺮﺽ .ﺭﲟﺎ ﻋﻠﻴﻨﺎ ﺃﻥ ﻧﻘﻮﻡ ﺑﻨﺴﺦ ﻛﻞ ﺣﻘﻞ ﻣﻦ ﺣﻘﻮﻝ ﺍﻟﻐﺮﺽ ،ﻭﻟﻜﻦ ﺭﲟﺎ ﻻﺗﻜﻮﻥ ﻛﻞ ﺍﳊﻘﻮﻝ
ﻣﻌﺮﻓﺔ Publicﺃﻱ ﻻﻧﺴﺘﻄﻴﻊ ﺍﻟﻮﺻﻮﻝ ﺇﻟﻴﻬﺎ ﲨﻴﻌﻬﺎ . ،
ﰲ ﻫﺬﺓ ﺍﳊﺎﻟﺔ ﻧﺴﺘﺨﺪﻡ ﻣﻨﻬﺞ ﺧﺎﺹ ﻳﻘﻮﻡ ﺑﻨﺴﺦ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺍﻟﺪﺍﺧﻠﻴﺔ ﻛﻠﻬﺎ ،ﺃﺻﻨﺎﻑ ﻣﻜﺘﺒﺔ ﺍﻟﻌﻨﺎﺻﺮ ﺍﳌﺮﺋﻴﺔ ﰲ ﺩﻟﻔﻲ ﻭﺍﻟﱵ ﰎ
ﺗﻮﺭﻳﺜﻬﺎ ﻣﻦ ﺍﻟﺼﻨﻒ Tpersistentﲤﻠﻚ ﺍﳌﻨﻬﺞ Assignﻭﺍﻟﺬﻱ ﻳﻘﻮﻡ ﺬﺓ ﺍﻟﻌﻤﻠﻴﺔ .
)ﻣﻼﺣﻈﺔ ﻫﺬﺍ ﺍﳌﻨﻬﺞ ﻏﲑ ﻣﺘﻮﻓﺮ ﰲ ﲨﻴﻊ ﺃﺻﻨﺎﻑ ﺍﻟـ VCLﺣﱴ ﺍﳌﻮﺭﺛﺔ ﻣﻦ Tpersistentﺃﺣﻴﺎﻧﺎ ( .
ﻣﻼﺣﻈﺔ :ﻧﺴﺘﻄﻴﻊ ﺗﺰﻭﻳﺪ ﺍﻷﺻﻨﺎﻑ ﺍﻟﱵ ﻧﻘﻮﻡ ﺑﻜﺘﺎﺑﺘﻬﺎ ﲟﻨﺎﻫﺞ ﺷﺒﻴﻬﻪ ﺑﺎﳌﻨﻬﺞ Assignﺑﺴﻬﻮﻟﺔ ﻣﻦ ﺩﺍﺧﻞ ﺷﻔﺮﺓ ﺍﻟﺼﻨﻒ
ﻹﻧﻨﺎ ﻧﺴﺘﻄﻴﻊ ﺍﻟﻮﻟﻮﺝ ﺇﱃ ﲨﻴﻊ ﺑﻴﺎﻧﺎﺕ ﺍﻟﺼﻨﻒ ﻣﺜﻼ ﻹﺿﺎﻓﺔ ﺍﳌﻨﻬﺞ Assignﺇﱃ ﺍﻟﺼﻨﻒ Tdateﺍﻟﺬﻱ ﻗﻤﻨﺎ ﺑﺒﻨﺎﺀﺓ ﺳﺎﺑﻘﺎ :
;)procedure TDate.Assign (Source: TDate
begin
;fDate := Source.fDate
;end
)ﻻﺣﻆ ﺃﻥ ﺍﳌﺘﺤﻮﻝ fDateﺍﻟﺬﻱ ﲣﺰﻥ ﺿﻤﻨﺔ ﻗﻴﻤﺔ ﺍﻟﺘﺎﺭﻳﺦ ﻻﻳﻜﻮﻥ ﻣﺘﺎﺣﺎ ﺧﺎﺭﺝ ﺍﻟﻮﺣﺪﺓ ﻹﻧﺔ ﻣﻌﺮﻑ ( private
٢٨
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﺗﻮﺟﺪ ﺛﻼﺙ ﻗﻮﺍﻋﺪ ﻹﺩﺍﺭﺓ ﺍﻟﺬﺍﻛﺮﺓ ﰲ ﺩﻟﻔﻲ ،ﻋﻠﻰ ﺍﻷﻗﻞ ﻟﺘﻜﻮﻥ ﻭﺍﺛﻘﺎ ﺃﻥ ﺍﻟﻨﻈﺎﻡ ﻳﻌﻤﻞ ﺑﺘﻨﺎﻏﻢ ﻣﻦ ﺩﻭﻥ ﻇﻬﻮﺭ ﺭﺳﺎﺋﻞ
ﺇﻧﺘﻬﺎﻙ ﺍﻟﺬﺍﻛﺮﺓ ،ﺃﻭ ﻣﻦ ﺩﻭﻥ ﺗﺮﻙ ﻣﺴﺎﺣﺎﺕ ﻏﲑ ﻣﺴﺘﺨﺪﻣﺔ ﳏﺠﻮﺯﺓ ﺩﻭﻥ ﲢﺮﻳﺮﻫﺎ .
ﺇﺫﺍ ﻛﻨﺖ ﺳﺘﻘﻮﻡ ﺑﺬﻟﻚ ﻳﺪﻭﻳﺎ ﺿﻤﻦ ﺷﻔﺮﺗﻚ ﺃﻭ ﺳﺘﺘﺮﻙ ﺩﻟﻔﻲ ﺗﻘﻮﻡ ﺑﺬﻟﻚ ﻋﻮﺿﺎ ﻋﻨﻚ ،ﻓﺈﻥ ﺫﻟﻚ ﻳﻌﺘﻤﺪ ﻋﻠﻰ ﺍﻟﻨﻤﻮﺫﺝ
ﺍﻟﺬﻱ ﺳﻮﻑ ﺗﻌﺘﻤﺪﺓ ﻣﻦ ﺑﲔ ﳕﺎﺫﺝ ﺇﺩﺍﺭﺓ ﺍﻟﺬﺍﻛﺮﺓ ﺍﻟﱵ ﺗﻘﺪﻣﻬﺎ ﺩﻟﻔﻲ .
ﻛﻠﻤﺎ ﻗﻤﺖ ﺑﺈﻧﺸﺎﺀ ﻏﺮﺽ ﻳﺪﻭﻳﺎ ﺿﻤﻦ ﺷﻔﺮﺗﻚ ،ﻋﻠﻴﻚ ﲢﺮﻳﺮﺓ ﻳﺪﻭﻳﺎ ﺃﻳﻀﺎ ،ﻭﺇﺫﺍ ﱂ ﺗﻘﻢ ﺑﺬﻟﻚ ﻓﺈﻥ ﺍﻟﺬﺍﻛﺮﺓ ﺍﻟﱵ •
ﻳﺴﺘﺨﺪﻣﻬﺎ ﻟﻦ ﲢﺮﺭ ﻛﻲ ﺗﺴﺘﻔﻴﺪ ﻣﻨﻬﺎ ﺑﻘﻴﺔ ﻋﻨﺎﺻﺮ ﺗﻄﺒﻴﻘﻚ ﺣﱴ ﻳﺘﻢ ﺇﺎﺀ ﺗﻨﻔﻴﺬ ﺍﻟﱪﻧﺎﻣﺞ .
ﺗﺴﺘﻄﻴﻊ ﲢﺪﻳﺪ ﻋﻨﺼﺮ ﻣﺎﻟﻚ ) (owner componentﻟﻠﻌﻨﺎﺻﺮ ﺍﻟﱵ ﺗﻘﻮﻡ ﺑﺈﻧﺸﺎﺀﻫﺎ ،ﺑﺘﻤﺮﻳﺮ ﺍﳌﺎﻟﻚ ﺇﱃ ﺑﺎﱐ ﺍﻟﻌﻨﺼﺮ •
ﺍﳉﺪﻳﺪ .ﻭﻳﺼﺒﺢ ﺍﳌﺎﻟﻚ ﻣﺴﺆﻭﻻ ﻋﻦ ﲢﺮﻳﺮ ﺫﺍﻛﺮﺓ ﻛﻞ ﺍﻟﻌﻨﺎﺻﺮ ﺍﻟﱵ ﳝﻠﻜﻬﺎ ،ﺑﻌﺒﺎﺭﺓ ﺃﺧﺮﻯ ﻋﻨﺪ ﲢﺮﻳﺮ ﺷﻜﻞ
) (Formﻓﺈﻥ ﻛﻞ ﺍﻟﻌﻨﺎﺻﺮ ﺍﻟﱵ ﺗﺘﺒﻊ ﻟﺔ ﺳﻴﺘﻢ ﲢﺮﻳﺮﻫﺎ ﻣﻌﻪ .ﻭﺑﺎﻟﺘﺎﱄ ﰲ ﺣﺎﻟﺔ ﺍﻟﻌﻨﺎﺻﺮ ) (Componentsﻋﻨﺪﻣﺎ
ﺗﻘﻮﻡ ﺑﺘﺤﺪﻳﺪ ﻋﻨﺼﺮ ﻣﺎﻟﻚ ﻟﻌﻨﺼﺮﻙ ،ﻻﺩﺍﻋﻲ ﻟﺘﺬﻛﺮ ﲢﺮﻳﺮﺓ ﻣﻦ ﺍﻟﺬﺍﻛﺮﺓ .ﻭﻫﺬﺍ ﻫﻮ ﺍﻟﺘﺼﺮﻑ ﺍﻟﻘﻴﺎﺳﻲ ﻟﻠﻌﻨﺎﺻﺮ
ﺍﻟﱵ ﻗﻤﻨﺎ ﺑﻮﺿﻌﻬﺎ ﻋﻠﻰ ﺍﻟﺸﻜﻞ Formﰲ ﺯﻣﻦ ﺍﻟﺘﺼﻤﻴﻢ ،ﺣﱴ ﺍﻟﺸﻜﻞ ﻭﺍﻟﺬﻱ ﻳﻌﺘﱪ ﻣﺎﻟﻜﺎ ﳌﻌﻈﻢ ﻋﻨﺎﺻﺮ ﺍﻟﺘﻄﺒﻴﻖ
ﻳﻜﻮﻥ ﳑﻠﻮﻛﺎ ﻣﻦ ﻗﺒﻞ ﺃﻏﺮﺍﺽ Applicationﻭﺍﻟﱵ ﲢﺮﺭ ﺁﻟﻴﺎ ﻋﻨﺪ ﺇﺎﺀ ﺍﻟﺘﻄﺒﻴﻖ .
ﻋﻨﺪﻣﺎ ﺗﻘﻮﻡ ﻣﻜﺘﺒﺔ RTLﺑﺘﺨﺼﻴﺺ ﺍﻟﺬﺍﻛﺮﺓ ﻣﻦ ﺃﺟﻞ ﺍﻟﺴﻼﺳﻞ ﻭﺍﳌﺼﻔﻮﻓﺎﺕ ﺍﻟﺪﻳﻨﺎﻣﻴﻜﻴﺔ ،ﻓﺈﺎ ﺳﺘﻘﻮﻡ ﺁﻟﻴﺎ •
ﺑﺘﺤﺮﻳﺮ ﺍﻟﺬﺍﻛﺮﺓ ﻋﻨﺪﻣﺎ ﳜﺮﺝ ﺍﳌﺮﺟﻊ ﻣﻦ ﳎﺎﻝ ﺍﻟﺮﺅﻳﺎ ،ﻟﻦ ﲢﺘﺎﺝ ﻟﺘﺤﺮﻳﺮ ﺳﻠﺴﻠﺔ ﳏﺮﻓﻴﺔ ،ﻋﻨﺪﻣﺎ ﺗﺼﺒﺢ ﻏﲑ ﻗﺎﻳﻠﺔ
ﻟﻠﻮﺻﻮﻝ ﺳﻴﺘﻢ ﲢﺮﻳﺮﻫﺎ .
٢٩
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﺇﺫﺍ ﻗﻤﺖ ﺑﺈﺳﺘﺪﻋﺎﺀ ﺍﳌﻨﻬﺞ Freeﺃﻭ ﺍﳍﺎﺩﻡ Destroyﺃﻛﺜﺮ ﻣﻦ ﻣﺮﺓ ،ﻓﺈﻥ ﺫﻟﻚ ﺳﻴﻮﻟﺪ ﺧﻄﺄ ﺑﻼ ﺷﻚ .ﻭﻟﻜﻦ ﺇﺫﺍ ﺿﺒﻄﺖ
ﻣﺘﺤﻮﻝ ﺍﻟﻐﺮﺽ ﺇﱃ Nilﻓﺈﻧﻚ ﺗﺴﺘﻄﻴﻊ ﺇﺳﺘﺪﻋﺎﺀ ﺍﳌﻨﻬﺞ Freeﺃﻛﺜﺮ ﻣﻦ ﻣﺮﺓ ﺩﻭﻥ ﺃﺧﻄﺎﺀ .
ﻣﻼﺣﻈﺔ :ﺭﲟﺎ ﺗﺘﺴﺎﺋﻞ ﳌﺎﺫﺍ ﺗﺴﺘﻄﻴﻊ ﺑﺈﻣﺎﻥ ﺃﻥ ﺗﺴﺘﺪﻋﻲ Freeﺇﺫﺍ ﻛﺎﻥ ﻣﺮﺟﻊ ﺍﻟﻐﺮﺽ ، NILﻭﻻﺗﺴﺘﻄﻴﻊ ﺇﺳﺘﺪﻋﺎﺀ
. Destroyﺍﻟﺴﺒﺐ ﺃﻥ Freeﻫﻲ ﻣﻨﻬﺞ ﻣﻌﺮﻑ ﻋﻠﻰ ﻣﻮﻗﻊ ﺫﺍﻛﺮﺓ ﻣﻌﻄﻰ .ﰲ ﺣﲔ ﺃﻥ ﺍﻹﺳﺘﺪﻋﺎﺀ ﺍﻹﻓﺘﺮﺍﺿﻲ Destroy
ﻳﺘﻢ ﲢﺪﻳﺪﺓ ﰲ ﺯﻣﻦ ﺍﻟﺘﺸﻐﻴﻞ ﺑﺎﻟﻨﻈﺮ ﺇﱃ ﺻﻨﻒ ﺍﻟﻐﺮﺽ ،ﻭﻫﻲ ﺗﻌﻠﻴﻤﺔ ﺧﻄﲑﺓ ﺟﺪﺍ ﰲ ﺣﺎﻝ ﺃﺳﺘﺨﺪﻣﺖ ﻭﱂ ﻳﻜﻦ ﺍﻟﻐﺮﺽ
ﻣﻮﺟﻮﺩﺍ .
ﺇﺳﺘﺨﺪﻡ ﺍﻟﺪﺍﻟﺔ ، FreeAndNillﺃﻭ ﺇﺿﺒﻂ ﻣﺮﺟﻊ ﺍﻟﻐﺮﺽ ﺇﱃ Nilﺑﻌﺪ ﺇﺳﺘﺪﻋﺎﺀ ﺍﳌﻨﻬﺞ . Free •
ﺗﺴﺘﻄﻴﻊ ﺇﺧﺘﺒﺎﺭ ﺇﺫﺍ ﻛﺎﻧﺖ ﻗﻴﻤﺔ ﻣﺮﺟﻊ ﻏﺮﺽ ﻣﺎ Nilﺑﺈﺳﺘﺨﺪﺍﻡ ﺍﻟﺘﺎﺑﻊ . Assigned
ﺗﺬﻛﺮ ﺃﻧﻪ ﺣﱴ ﻟﻮﻛﺎﻧﺖ ﺍﻟﻘﻴﻤﺔ ﻟﻴﺴﺖ Nilﻓﻬﺬﺍ ﻻ ﻳﻌﲏ ﺃﻥ ﺍﳌﺆﺷﺮ ﺻﺎﱀ ﻟﻠﺘﻌﺎﻣﻞ .ﻣﺜﺎﻝ ﺇﻥ ﺇﺳﺘﺨﺪﺍﻡ ﺍﳌﻨﻬﺞ Freeﺳﻴﺤﺮﺭ
ﺍﻟﻐﺮﺽ ﻭﻟﻜﻨﺔ ﻟﻦ ﻳﻀﺒﻄﺔ ﺇﱃ Nilﻭﺑﺎﻟﺘﺎﱄ ﺍﻟﺘﻌﻠﻴﻤﺔ ﺍﻟﺘﺎﻟﻴﺔ ﺳﺘﺴﺒﺐ ﺧﻄﺄ .
;ToDestroy.Free
if ToDestroy <> nil then
;ToDestroy.DoSomething
٣٠
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﻏﺎﻟﺒﺎ ﻣﺎ ﳓﺘﺎﺝ ﻟﺒﻨﺎﺀ ﳕﻮﺫﺝ ﳐﺘﻠﻒ ﻗﻠﻴﻼ ﻣﻦ ﺻﻨﻒ ﻣﻮﺟﻮﺩ ،ﺑﺪﻻ ﻣﻦ ﺑﻨﺎﺀ ﺻﻨﻒ ﺟﺪﻳﺪ ﻣﻦ ﺍﻟﺒﺪﺍﻳﺔ ،ﺭﲟﺎ ﳓﺘﺎﺝ ﺇﺿﺎﻓﺔ
ﻣﻨﺎﻫﺞ ﺟﺪﻳﺪﺓ ﺃﻭ ﺧﺼﺎﺋﺺ ﺃﻭ ﺗﻌﺪﻳﻞ ﺃﺧﺮﻯ ﻣﻮﺟﻮﺩﺓ .
ﻧﺴﺘﻄﻴﻊ ﻓﻌﻞ ﺫﻟﻚ ﺑﻄﺮﻳﻘﺘﲔ ،ﻧﺴﺦ ﺍﻟﺸﻔﺮﺓ ﻣﻦ ﻫﻨﺎﻙ ﻭﻟﺼﻘﻬﺎ ﻫﻨﺎ ) .ﻳﺪﻝ ﻋﻠﻰ ﺿﻌﻒ ﺧﱪﺓ ﺑﺎﻟﱪﳎﺔ ﻣﺎﱂ ﺗﻮﺟﺪ ﻏﺎﻳﺔ ﻣﱪﺭﺓ
ﻟﻪ ( ،ﻭﺑﺬﻟﻚ ﺳﺘﻀﺎﻋﻒ ﺷﻔﺮﺗﻚ ﻣﺮﺗﲔ ،ﻧﺎﻫﻴﻚ ﻋﻦ ﺍﻷﺧﻄﺎﺀ ،ﻭﺍﻟﻐﺮﻕ ﰲ ﺗﻔﺼﻴﻼﺕ ﺗﺒﻌﺪﻙ ﻋﻦ ﻣﺸﺮﻭﻋﻚ ﺍﻷﺳﺎﺳﻲ
ﺑﺒﺴﺎﻃﺔ ،ﻻ ﺗﻜﻦ ﻣﻦ ﺍﻟﺬﻳﻦ ﻳﺘﺒﻌﻮﻥ ﻫﺬﺍ ﺍﻟﻨﻮﻉ ﻣﻦ ﺍﳊﻠﻮﻝ ﻛﺤﻠﻮﻝ ﺃﺳﺎﺳﻴﺔ .ﳌﺎﺫﺍ ﻻ ﺗﻘﻮﻡ ﺑﺪﻻ ﻣﻦ ﺫﻟﻚ ﺑﺈﺳﺘﺨﺪﺍﻡ ﺇﺣﺪﻯ
ﺃﺭﻭﻉ ﻣﻴﺰﺍﺕ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴﺔ :ﺃﻻ ﻭﻫﻲ ﺍﻟﻮﺭﺍﺛـــﺔ ). (inheritance
ﻭﺭﺍﺛﺔ ﺻﻨﻒ ﻣﻮﺟﻮﺩ ﻋﻤﻠﻴﺔ ﺳﻬﻠﺔ ﺍﻟﺘﺤﻘﻴﻖ ﺑﺈﺳﺘﺨﺪﺍﻡ ﺩﻟﻔﻲ ،ﻋﻠﻴﻚ ﻓﻘﻂ ﺃﻥ ﺗﺬﻛﺮ ﺇﺳﻢ ﺍﻟﺼﻨﻒ ﺍﳌﻮﺭﻭﺙ ﰲ ﺗﺮﻭﻳﺴﺔ
ﺗﻌﺮﻳﻒ ﺍﻟﺼﻨﻒ ﺍﳉﺪﻳﺪ .ﻻﺣﻆ ﺃﻥ ﺷﻔﺮﺓ ﻣﺸﺮﻭﻉ ﺟﺪﻳﺪ ﰲ ﺩﻟﻔﻲ ﲢﻮﻱ ﺍﻟﺘﻌﺮﻳﻒ ﺍﻟﺘﺎﱄ :
type
)TForm1 = class(TForm
;end
ﻫﺬﺓ ﻫﻲ ﺍﻟﻮﺭﺍﺛﺔ ﻳﺎﺻﺪﻳﻘﻲ ،ﺍﻟﺘﻌﺮﻳﻒ ﺍﻟﺴﺎﺑﻖ ﻳﺪﻝ ﻋﻠﻰ ﺃﻥ Tform1ﻳﺮﺙ ﻛﻞ ﺻﻔﺎﺕ ﺍﻟﺼﻨﻒ ، Tformﺍﳊﻘﻮﻝ ،ﺍﳌﻨﺎﻫﺞ
،ﺍﻷﺣﺪﺍﺙ ..ﻛﻞ ﺷﻲﺀ ،ﺗﺴﺘﻄﻴﻊ ﺃﻥ ﺗﺴﺘﺪﻋﻲ ﺃﻱ ﻣﻨﻬﺞ ﻋﺎﻡ Publicﻣﻌﺮﻑ ﰲ ﺍﻟﺼﻨﻒ Tformﻣﻦ ﻏﺮﺽ ﻣﻦ ﺍﻟﺼﻨﻒ
ﺍﻟﻮﺍﺭﺙ ، Tform1ﻭﺍﻟﺬﻱ ﺑﺪﻭﺭﺓ ﻭﺭﺙ ﺑﻌﺾ ﺍﻟﺼﻔﺎﺕ ﻣﻦ ﺻﻨﻒ ﺃﺏ ﻟﻪ ﺣﱴ ﻧﺼﻞ ﺇﱃ ﺍﻟﺼﻨﻒ ﺍﻟﺴﻠﻒ . Tobject
ﺑﺈﻣﻜﺎﻧﻚ ﺇﺿﺎﻓﺔ ﺑﻴﺎﻧﺎﺗﻚ ﺍﳋﺎﺻﺔ ﻟﻠﺼﻨﻒ ﺍﳉﺪﻳﺪ ،ﺃﻭ ﺗﻌﺪﻳﻞ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺍﳌﻮﺭﻭﺛﺔ ﻣﻦ ﺍﻟﺼﻨﻒ ﺍﻷﺏ ﺑﺈﻋﺎﺩﺓ ﺗﻌﺮﻳﻔﻬﺎ ﻟﻜﻦ ﰲ
ﻧﻔﺲ ﺍﻟﻮﺣﺪﺓ .
ﻣﺜﻼ ﺇﺫﺍ ﺃﺭﺩﻧﺎ ﺃﻥ ﻧﺒﲏ ﺻﻨﻒ ﺟﺪﻳﺪ ﻣﺸﺘﻖ ﻣﻦ ﺍﻟﺼﻨﻒ Tdateﺍﻟﺬﻱ ﺳﺒﻖ ﻭﺑﻨﻴﻨﺎﻩ ،ﻭﻧﻌﺪﻝ ﰲ ﺍﳌﻨﻬﺞ GetTextﺍﳋﺎﺹ ﺑﺔ
type
)TNewDate = class (TDate
public
;function GetText: string
;end
…
;function TNewDate.GetText: string
begin
;)GetText := FormatDateTime ('dddddd', fDate
;end
ﻳﻜﻔﻲ ﺇﻋﺎﺩﺓ ﺗﻌﺮﻳﻒ ﺍﳌﻨﺎﻫﺞ ﺍﳌﻮﺟﻮﺩﺓ ﺑﻨﻔﺲ ﺍﻹﺳﻢ ﺣﱴ ﳓﺼﻞ ﻋﻠﻰ ﻧﺴﺨﺘﻨﺎ ﺍﳋﺎﺻﺔ ﻣﻨﻬﺎ ،ﻫﺬ ﺍﻟﻌﻤﻞ ﻳﻮﻓﺮ ﺍﳉﻬﺪ ﻭﺍﻟﺘﻌﺐ ،
ﻭﺳﺘﻘﻮﻡ ﺩﻟﻔﻲ ﺑﺈﺳﺘﺒﺪﺍﻝ ﺍﻟﺘﻌﺮﻳﻒ ﺍﻟﻘﺪﱘ ﺑﺎﳉﺪﻳﺪ ﻭﺳﻴﺴﺘﺨﺪﻡ ﰲ ﻛﻞ ﻣﺮﺓ ﻳﺘﻢ ﺇﺳﺘﺪﻋﺎﺀﺓ ﻓﻴﻬﺎ .
٣١
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
GetText ﻣﻼﺣﻈﺔ :ﰲ ﺍﳌﺜﺎﻝ ﺍﻟﺴﺎﺑﻖ ﻧﻀﻊ ﺗﻌﺮﻳﻒ TnewDateﺿﻤﻦ ﻧﻔﺲ ﺍﻟﻮﺣﺪﺓ ﺍﻟﱵ ﻋﺮﻓﻨﺎ ﺎ Tdateﻹﻥ ﺍﳌﻨﻬﺞ
ﻳﺴﺘﺨﺪﻡ ﺍﳌﺘﺤﻮﻝ ﺍﳋﺎﺹ fDateﺍﳌﻌﺮﻑ ﻛـ Privateﺿﻤﻦ Tdateﻭﻻﳝﻜﻦ ﺍﻟﻮﺻﻮﻝ ﺇﻟﻴﺔ ﻣﻦ ﺧﺎﺭﺝ ﺍﻟﻮﺣﺪﺓ .
ﻛﻤﺎ ﻻﺣﻈﺖ ﺃﻥ ﺷﻔﺮﺓ ﺍﳌﻨﻬﺞ GetTextﺍﳋﺎﺻﺔ ﺑﺎﻟﺼﻨﻒ TnewDateﺳﺘﺘﺮﺟﻢ ﺑﻼ ﺃﺧﻄﺎﺀ ﻓﻘﻂ ﺇﻥ ﲤﺖ ﺇﺿﺎﻓﺘﻬﺎ ﰲ ﻧﻔﺲ
ﻭﺣﺪﺓ ﺍﻟﺼﻨﻒ ﺍﻷﺳﺎﺱ . Tdateﻹﺎ ﻛﻤﺎ ﻭﺿﺤﻨﺎ ﲢﺎﻭﻝ ﺩﺧﻮﻝ ﺍﳌﺘﺤﻮﻝ fDateﻭﺍﻟﺬﻱ ﻫﻮ ﻣﺘﺤﻮﻝ ﻣﻮﺿﻌﻲ ، Private
ﺇﺫﺍ ﺃﺭﺩﻧﺎ ﺃﻥ ﻧﻀﻊ ﺍﻟﺼﻨﻒ ﺍﳌﺸﺘﻖ ﰲ ﻭﺣﺪﺓ ﺟﺪﻳﺪﺓ ﺑﺪﻭﻥ ﺃﻥ ﳒﻌﻞ ﺍﳌﺘﺤﻮﻝ fDateﻣﺘﺤﻮﻝ ﻋﺎﻡ Publicﳝﻜﻦ ﺍﻟﻮﺻﻮﻝ ﺇﻟﻴﺔ
ﻣﻦ ﺃﻱ ﻣﻜﺎﻥ ،ﻓﺈﻧﻨﺎ ﺳﻨﺠﺪ ﻃﺮﻳﻘﺘﲔ ﲢﻘﻘﺎﻥ ﺫﻟﻚ
-ﺗﻌﺮﻳﻒ ﺍﳌﺘﺤﻮﻝ fDateﻛﻤﺘﺤﻮﻝ ﳏﻤﻲ ﺃﻱ ) (Protectedﺑﺪﻻ ﻣﻦ ﺍﳌﺘﺤﻮﻝ ﺍﻟﻌﺎﻡ ﺃﻭ ﺍﶈﻠﻲ ،ﺇﺫﺍ ﻛﻨﺖ ﺗﺘﺬﻛﺮ ﺇﻥ
ﻫﺬﺍ ﺍﻟﻨﻮﻉ ﻳﺴﻤﺢ ﻓﻘﻂ ﻟﻸﺻﻨﺎﻑ ﺍﳌﺸﺘﻘﺔ ﻣﻦ ﺍﻟﺼﻨﻒ ﺍﻷﺳﺎﺳﻲ ﺑﺎﻟﺪﺧﻮﻝ ﻟﻠﺒﻴﺎﻧﺎﺕ .
ﺭﲟﺎ ﻻﺣﻈﺖ ﻣﻌﻲ ﺃﻥ ﺍﻟﻄﺮﻳﻘﺔ ﺍﻷﻭﱃ ﻫﻲ ﺍﻷﻓﻀﻞ ﻹﺎ ﺃﻛﺜﺮ ﻋﻤﻮﻣﻴﺔ ﻋﻨﺪﻣﺎ ﻧﻮﺭﺙ ﺍﻟﺼﻨﻒ ﻟﻌﺪﺩ ﻛﺒﲑ ﻣﻦ ﺍﻷﺻﻨﺎﻑ
ﺍﻟﻔﺮﻋﻴﺔ ،ﻭﺃﻧﺼﺤﻚ ﺑﺈﺗﺒﺎﻋﻬﺎ ﺩﺍﺋﻤﺎ ،ﺣﱴ ﻟﻮ ﱂ ﲡﺪ ﺣﺎﺟﺔ ﺣﺎﻟﻴﺎ ﻟﺘﻌﺮﻳﻒ ﻣﻌﻄﻴﺎﺕ ﳏﻤﻴﺔ ﻗﻢ ﺑﺬﻟﻚ ﻣﻦ ﺃﺟﻞ ﺗﻮﺭﻳﺚ
ﺃﺻﻨﺎﻑ ﺟﺪﻳﺪﺓ ﻣﺴﺘﻘﺒﻼ ،ﺍﻟﺒﻴﺎﻧﺎﺕ ﺍﶈﻤﻴﺔ ﲡﻌﻞ ﺍﻟﺼﻨﻒ ﻗﺎﺑﻞ ﻟﻠﻮﺻﻮﻝ ﺑﺸﻜﻞ ﻣﻨﺎﺳﺐ ﻟﺘﻘﻨﻴﺔ ﺍﻟﻮﺭﺍﺛﺔ .
ﺭﲟﺎ ﺗﻘﻮﻝ ﺇﻥ ﺫﻟﻚ ﺧﺮﻭﺝ ﻋﻦ ﻗﺎﻋﺪﺓ ﺍﻟﺘﻐﻠﻴﻒ ﺍﻟﻜﺎﻣﻞ ﰲ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴﺔ )ﺍﻟﱵ ﺗﻘﻮﻝ ﺑﻴﺎﻧﺎﺕ ﳏﻠﻴﺔ ﻣﻨﺎﻫﺞ ﻋﺎﻣﺔ( ،ﺍﳉﻮﺍﺏ
ﻧﻌﻢ ﺇﱃ ﺣﺪ ﻣﺎ ،ﻭﻟﺬﻟﻚ ﻋﻠﻴﻨﺎ ﺃﻥ ﻧﻜﻮﻥ ﻣﻨﺘﺒﻬﲔ ﺃﻧﻨﺎ ﻟﻦ ﳓﺼﻞ ﻋﻠﻰ ﻛﺎﻣﻞ ﻣﻴﺰﺍﺕ ﺍﻟﺘﻐﻠﻴﻒ ﻣﺎﱂ ﻧﺘﺒﻌﺔ ﺑﺸﻜﻞ ﺟﻴﺪ ،
ﻻﺣﻆ ﻣﺜﻼ ﰲ ﺣﺎﻟﺔ ﻗﻤﻨﺎ ﺑﺘﻮﺭﻳﺚ ﻋﺸﺮﺍﺕ ﺍﻷﺻﻨﺎﻑ ﻣﻦ ﺻﻨﻒ ﻣﺎ ،ﺇﻥ ﺗﻐﻴﲑ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺍﶈﻤﻴﺔ Protectedﰲ ﻫﺬﺍ
ﺍﻟﺼﻨﻒ ﺭﲟﺎ ﻳﻀﻄﺮﻧﺎ ﻟﺘﻐﲑ ﻣﺎﻳﻘﺎﺑﻠﻬﺎ ﰲ ﻛﻞ ﻣﻦ ﺍﻷﺻﻨﺎﻑ ﺍﳌﺸﺘﻘﺔ .
ﺑﻜﻠﻤﺔ ﺃﺧﺮﻯ ﺍﳌﺮﻭﻧﺔ ،ﻗﺎﺑﻠﻴﺔ ﺍﻟﺘﻮﺳﻊ ،ﺍﻟﺘﻐﻠﻴﻒ ،ﻏﺎﻟﺒﺎ ﻣﺎ ﺗﻜﻮﻥ ﺃﻫﺪﺍﻑ ﻣﺘﻨﺎﺯﻋﺔ ،ﻭﻣﻦ ﺍﻟﺼﻌﺐ ﲢﻘﻴﻘﻬﺎ ﲨﻴﻌﺎ ،
ﻋﻨﺪﻣﺎ ﳛﺼﻞ ﺫﻟﻚ ﻋﻠﻴﻚ ﺃﻥ ﺗﻔﻀﻴﻞ ﺍﻟﺘﻐﻠﻴﻒ ﻣﻦ ﺑﻴﻨﻬﺎ .ﺇﺫﺍ ﻛﺎﻥ ﻣﻦ ﺍﳌﻤﻜﻦ ﲢﻘﻴﻖ ﺫﻟﻚ ﺑﺪﻭﻥ ﺍﻟﺘﻀﺤﻴﺔ ﺑﺎﳌﺮﻭﻧﺔ ﻓﺈﻥ
٣٢
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﺫﻟﻚ ﺳﻴﻜﻮﻥ ﳑﺘﺎﺯﺍ .ﻏﺎﻟﺒﺎ ﻣﺎ ﻳﺘﻢ ﲢﻘﻴﻖ ﻫﺬﺍ ﺍﳊﻞ ﺍﻟﻮﺳﻄﻲ ﺑﺈﺳﺘﺨﺪﺍﻡ ﻣﺎﻳﻌﺮﻑ ﺑﺎﳌﻨﺎﻫﺞ ﺍﻹﻓﺘﺮﺍﺿﻴﺔ ﻭﺍﻟﱵ ﺳﻨﺄﰐ ﻋﻠﻰ
ﺫﻛﺮﻫﺎ ﻗﺮﻳﺒﺎ ﲢﺖ ﻋﻨﻮﺍﻥ ﺍﻟﺘﻐﻠﻴﻒ ﺍﳌﺘﺄﺧﺮ ﻭﺗﻌﺪﺩﻳﺔ ﺍﻷﺷﻜﺎﻝ .ﻭﺭﲟﺎ ﺇﺫﺍ ﱂ ﲣﺘﺮ ﺍﻟﺘﻐﻠﻴﻒ ﻣﻦ ﻫﺬﺓ ﺍﳊﻠﻮﻝ ﻣﻦ ﺃﺟﻞ
ﲢﻘﻴﻖ ﺳﺮﻋﺔ ﰲ ﻛﺘﺎﺑﺔ ﺍﻟﺸﻔﺮﺓ ﻣﺜﻼ ،ﻓﺈﻧﻚ ﻋﻨﺪﻫﺎ ﻟﻦ ﺗﻜﻮﻥ ﻣﺘﺒﻊ ﻟﻘﻮﺍﻋﺪ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴﺔ ﺑﺸﻜﻞ ﺟﻴﺪ .
ﳏﺪﺩﺍﺕ ﺍﻟﻮﺻﻮﻝ Privateﻭ Protectedﺗﺴﻤﺢ ﺑﺎﻟﺪﺧﻮﻝ ﺇﱃ ﺑﻴﺎﻧﺎﺎ ﻣﻦ ﻧﻔﺲ ﺍﻟﻮﺣﺪﺓ ﻓﻘﻂ ،ﺍﳉﺪﻳﺮ ﺑﺎﻟﺬﻛﺮ ﻫﻨﺎ ﺃﻧﺔ
ﻣﻦ ﺍﳌﻤﻜﻦ ﺍﻟﺪﻭﺭﺍﻥ ﻋﻠﻰ ﺍﳌﻮﺿﻮﻉ ﰲ ﺣﺎﻟﺔ ﺍﶈﺪﺩ Protectedﻭﺍﻟﺪﺧﻮﻝ ﺇﱃ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺍﶈﻤﻴﺔ ﺍﳋﺎﺻﺔ ﺑﺼﻨﻒ ﻣﺎ .
ﺍﻟﻄﺮﻳﻘﺔ ﺗﻌﺘﻤﺪ ﻋﻠﻰ ﻣﺎﺷﺮﺣﻨﺎﺓ ﺳﺎﺑﻘﺎ ،ﺃﻧﻪ ﳝﻜﻦ ﺍﻟﻮﺻﻮﻝ ﺇﱃ ﺍﻟﺒﻴﺎﻧﺎﺕ ﺍﶈﻤﻴﺔ ﻟﺼﻨﻒ ﻣﻦ ﺍﻷﺻﻨﺎﻑ ﺍﳌﺸﺘﻘﺔ ﻣﻨﻪ .
ﻟﺬﻟﻚ ﻧﻘﻮﻡ ﺑﺈﺷﺘﻘﺎﻕ ﺻﻨﻒ ﺟﺪﻳﺪ ﻣﻦ ﺍﻟﺼﻨﻒ ﺍﻟﺬﻱ ﻧﺮﻳﺪ ﺩﺧﻮﻝ ﺑﻴﺎﻧﺎﺗﺔ ﻣﺜﻼ ﻧﺸﺘﻖ ﺍﻟﺼﻨﻒ TtestHackﻣﻦ ﺍﻟﺼﻨﻒ
،Ttestﻭﻋﻠﻰ ﺇﻓﺘﺮﺍﺽ ﺍﳌﺘﻐﲑ ProtectedDataﻣﻌﺮﻑ ﻛﻤﺘﻐﲑ ﳏﻤﻲ ﺿﻤﻦ ﺍﻟﺼﻨﻒ Ttestﻛﺎﻟﺘﺎﱄ :
type
Ttest = class
protected
;ProtectedData: Integer
;end
…
var
;Obj: Ttest
begin
;Obj := Ttest.Create
;TtestHack (Obj).ProtectedData := 20
٣٣
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﻛﻠﻨﺎ ﻧﺘﻌﺎﻣﻞ ﻣﻊ ﺍﻟﻌﻨﺼﺮ ﺍﳉﻤﻴﻞ ، DBNavigatorﻭﻟﻜﻦ ﻫﺬﺍ ﺍﻟﻌﻨﺼﺮ ﻻ ﳛﻮﻱ ﺧﺎﺻﻴﺔ ﻟﻀﺒﻂ ﺍﻟﻠﻮﻥ ،ﺇﺫﺍ ﻋﻠﻤﺖ ﺃﻥ
ﺍﳌﺘﺤﻮﻝ Colorﻣﺘﺤﻮﻝ ﳏﻤﻲ ﻟﻠﺼﻨﻒ TDBNavigatorﺇﻛﺘﺐ ﺷﻔﺮﺓ ﲢﻮﻳﻞ ﺍﻟﻠﻮﻥ ﺇﱃ ﺍﻷﲪﺮ .
ﺍﳊﻞ :
begin
;NewNav(DBNavigator1).Color:=clred
;end
ﻻﺑﺪ ﻣﻦ ﺍﻹﺷﺎﺭﺓ ﺃﻥ ﻫﺬﺓ ﺍﻟﻌﻤﻠﻴﺔ ﻟﻴﺴﺖ ﻗﻴﺎﺳﻴﺔ ،ﻣﻊ ﺃﺎ ﺗﺼﻠﺢ ﻭﳝﻜﻦ ﺇﺳﺘﺨﺪﺍﻣﻬﺎ ﰲ ﻛﺜﲑ ﻣﻦ ﺍﻷﺣﻴﺎﻥ ،ﻭﻟﻜﻦ ﳌﺎﺫﺍ
ﺟﻌﻞ ﻛﺎﺗﺐ ﺍﻟﺼﻨﻒ ﺍﻷﺳﺎﺳﻲ ﺍﻟﺒﻴﺎﻧﺎﺕ ﳏﻤﻴﺔ ﻟﻮ ﺃﻧﺔ ﻳﺮﻳﺪ ﻣﺸﺎﺭﻛﺘﻬﺎ ،ﻻﺣﻆ ﻣﺜﻼ ﰲ ﺍﳌﺜﺎﻝ ﺍﻟﺴﺎﺑﻖ ﺃﻧﻨﺎ ﺃﺿﻄﺮﺭﻧﺎ
ﻟﻀﺒﻂ ﺍﳋﺎﺻﻴﺔ Flatﻭﻟﻦ ﺗﻈﻬﺮ ﺍﻟﺘﻐﲑﺍﺕ ﺑﻼ ﺫﻟﻚ ،ﺍﳋﻼﺻﺔ ﳝﻜﻨﻚ ﺇﺳﺘﺨﺪﺍﻡ ﻫﺬﺓ ﺍﻟﻄﺮﻳﻘﺔ ﻟﺘﺤﻘﻴﻖ ﻏﺎﻳﺔ ﻣﺎ،
ﻭﻟﻜﻦ ﺃﺷﺪﺩ ﻋﻠﻴﻚ ﺃﻥ ﺗﺘﺄﻛﺪ ﻣﻦ ﺃﺎ ﺍﻟﻄﺮﻳﻘﺔ ﺍﻷﺧﲑﺓ ﻟﺬﻟﻚ .
ﻣﻼﺣﻈﺔ :ﳚﺐ ﺃﻥ ﻳﻜﻮﻥ ﺗﻌﺮﻳﻒ ﺍﻟﺼﻨﻒ ﺍﳌﺸﺘﻖ ﻭ ﺷﻔﺮﺓ ﺍﻟﺪﺧﻮﻝ ﻟﻠﺼﻨﻒ ﺍﻷﺏ ﰲ ﻧﻔﺲ ﺍﻟﻮﺣﺪﺓ .ﺃﻱ ﺍﻟﺴﻄﺮ
;NewNav(DBNavigator1).Color:=clred
ﳚﺐ ﺃﻥ ﻳﻜﻮﻧﺎ ﺑﻨﻔﺲ ﺍﻟﻮﺣﺪﺓ ،ﻭﻋﻨﺪ ﻓﺼﻠﻬﻤﺎ ﰲ ﻭﺣﺪﺍﺕ ﳐﺘﻠﻔﺔ ﻓﺈﻥ ﺍﻟﺸﻔﺮﺓ ﺍﻟﺴﺎﺑﻘﺔ ﻟﻦ ﺗﺘﺮﺟﻢ .
٣٤
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﺍﻟﺒﺎﺳﻜﺎﻝ ﻟﻐﺔ ﳕﻮﺫﺟﻴﺔ ﻭﻣﺜﺎﻟﻴﺔ ﺑﺸﻜﻞ ﺻﺎﺭﻡ ،ﻭﻫﺬﺍ ﻳﻌﲏ ﺃﻧﻚ ﻟﻦ ﺗﺴﺘﻄﻴﻊ ﻣﺜﻼ ﺃﻥ ﺗﻨﺴﺐ ﻗﻴﻤﺔ ﺭﻗﻤﻴﺔ ﺇﱃ ﻗﻴﻤﺔ ﻧﺼﻴﺔ ﺃﻭ
ﺍﻟﻌﻜﺲ ﺑﺪﻭﻥ ﺇﺟﺮﺍﺀ ﲢﻮﻳﻞ ﺑﺪﻭﺍﻝ ﺍﻟﺘﺤﻮﻳﻞ ﺍﳌﻨﺎﺳﺒﺔ ﺍﻟﱵ ﺗﺰﻭﺩﻙ ﺩﻟﻔﻲ ﺎ ،
ﻭﻟﻠﺘﺒﺴﻴﻂ ﻓﺈﻥ ﺩﻟﻔﻲ ﺗﺴﻤﺢ ﻟﻚ ﰲ ﺑﻌﺾ ﺍﻷﺣﻴﺎﻥ ﻧﺴﺐ ﳕﻄﲔ ﳐﺘﻠﻔﲔ ،ﰲ ﺣﺎﻝ ﻛﺎﻥ ﺃﺣﺪﳘﺎ ﻳﺴﺘﻮﻋﺐ ﺍﻵﺧﺮ ،ﻣﺜﻼ
ﻻﺣﻆ ﺃﻧﻨﺎ ﻧﺴﺘﻄﻴﻊ ﻧﺴﺐ ﻣﺘﺤﻮﻝ Integerﺇﱃ ﻣﺘﺤﻮﻝ Realﺑﺪﻭﻥ ﺃﺧﻄﺎﺀ ،،ﻭﺑﺎﻟﻄﺒﻊ ﺍﳊﺎﻟﺔ ﺍﳌﻌﺎﻛﺴﺔ ﻏﲑ ﺻﺤﻴﺤﺔ .
;var i:integer
;r:real
begin
;i:=r !!!//error
;End
ﻭﻫﺬﺍ ﺍﻹﺳﺘﺜﻨﺎﺀ ﻣﻬﻢ ﰲ ﺣﺎﻟﺔ ﺃﳕﺎﻁ ﺍﻷﺻﻨﺎﻑ ،ﻓﺈﺫﺍ ﻗﻤﺖ ﻣﺜﻼ ﺑﺘﻌﺮﻳﻒ ﺻﻨﻒ ﺟﺪﻳﺪ ﻣﺜﻞ Tanimalﻭﺃﺷﺘﻘﻴﺖ ﻣﻨﻪ
ﺻﻨﻒ ﻭﻟﻨﻘﻞ ﻣﺜﻼ ، Tdogﺗﺴﺘﻄﻴﻊ ﻋﻨﺪﻫﺎ ﺃﻥ ﺗﻨﺴﺐ ﻏﺮﺽ ﻣﻦ ﺍﻟﺼﻨﻒ Tdogﺇﱃ ﻣﺘﺤﻮﻝ ﻣﻦ ﺍﻟﺼﻨﻒ ، Tanimal
ﻹﻥ ﺍﻟﻜﻠﺐ ﺣﻴﻮﺍﻥ ،ﻭﻟﻜﻦ ﻟﻴﺲ ﺑﺎﻟﻀﺮﻭﺭﺓ ﺃﻥ ﻳﻜﻮﻥ ﻛﻞ ﺣﻴﻮﺍﻥ ﻛﻠﺐ ،ﻭﺑﻨﺎﺀ ﻋﻠﻰ ﺫﻟﻚ ﺍﻟﻌﻜﺲ ﻏﲑ ﳑﻜﻦ :
var
;MyAnimal: Tanimal
;MyDog: Tdog
begin
;MyAnimal := MyDog // OK
;MyDog := MyAnimal !!!// error
٣٥
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﺗﻌﺘﻤﺪ ﺗﻮﺍﺑﻊ ﺍﻟﺒﺎﺳﻜﺎﻝ ﻭﺇﺟﺮﺍﺀﺍﺎ ﻋﺎﺩﺓ ﻋﻠﻰ ﺍﻟﺘﺤﺪﻳﺪ ﺍﻟﺴﺎﻛﻦ ﺃﻭ ﺍﳌﺒﻜﺮ ) ، (static or early bindingﻭﻫﺬﺍ ﻳﻌﲏ ﺃﻥ
ﺍﳌﺘﺮﺟﻢ ﺳﻴﻘﻮﻡ ﺑﺘﺤﻠﻴﻞ ﺍﻹﺳﺘﺪﻋﺎﺀ ﻭﺇﺳﺘﺒﺪﺍﻝ ﺍﻟﻄﻠﺐ ﺑﺈﺳﺘﺪﻋﺎﺀ ﳌﻮﻗﻊ ﺍﻟﺬﺍﻛﺮﺓ ﺍﳊﺎﻭﻱ ﻋﻠﻰ ﺍﻟﺘﺎﺑﻊ ﺃﻭ ﺍﻹﺟﺮﺍﺀ )ﻋﻨﻮﺍﻥ ﺍﻟﺮﻭﺗﲔ(
،ﻭﻫﺬﺍ ﻳﻌﲏ ﺍﻟﺘﺤﺪﻳﺪ ﺍﳌﺴﺒﻖ ﻟﻠﺘﺎﺑﻊ ﺃﻭ ﺍﻹﺟﺮﺍﺀ ﺍﻟﺬﻱ ﺳﻮﻑ ﻳﺘﻢ ﺇﺳﺘﺪﻋﺎﺀﺓ ،ﻭﻳﻘﻮﻡ ﺍﳌﺘﺮﺟﻢ ﺬﺍ ﺍﻟﺘﺤﺪﻳﺪ ﳊﻈﺔ ﺗﺮﲨﺔ
ﺍﳌﺸﺮﻭﻉ ﻭﺑﺎﻟﺘﺎﱄ ﺍﻟﺘﺼﺮﻑ ﰲ ﻭﻗﺖ ﺍﻟﺘﻨﻔﻴﺬ ﻣﻌﺮﻭﻑ ﻭﳏﺪﺩ ﻣﻨﺬ ﺗﺮﲨﺔ ﺍﳌﺸﺮﻭﻉ .
ﺍﳌﺘﺄﺧﺮ) dynamic or ﻟﻐﺎﺕ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴﺔ ﺍﻟﺘﻮﺟﺔ ) (OOPﺗﺴﻤﺢ ﺑﻨﻮﻉ ﺁﺧﺮ ﻣﻦ ﺍﻟﺘﺤﺪﻳﺪ ﻳﺴﻤﻰ ﺍﻟﺘﺤﺪﻳﺪ ﺍﻟﺪﻳﻨﺎﻣﻴﻜﻲ ﺃﻭ
، (late bindingﻭﰲ ﻫﺬﺍ ﺍﳊﺎﻟﺔ ﻓﺈﻥ ﺍﻟﻌﻨﻮﺍﻥ ﺍﻟﻔﻌﻠﻲ ﺍﻟﺬﻱ ﺳﻮﻑ ﻳﺴﺘﺪﻋﻰ ﻟﻦ ﻳﺘﻢ ﲢﺪﻳﺪﺓ ﺣﱴ ﻭﻗﺖ ﺍﻟﺘﺸﻐﻴﻞ ،ﻭﻳﻌﺘﻤﺪ
ﺍﻟﺘﺤﺪﻳﺪ ﻋﻠﻰ ﳕﻂ ﺍﳌﻨﺘﺴﺦ ﺍﻟﺬﻱ ﻗﺎﻡ ﺑﺎﻟﻄﻠﺐ .
ﺗﺴﻤﻰ ﻫﺬﺓ ﺍﻟﺘﻘﻨﻴﺔ ﺗﻌﺪﺩﻳﺔ ﺍﻷﺷﻜﺎﻝ ( polymorphism)،ﺑﺎﻟﻴﻮﻧﺎﻧﻴﺔ ﺗﻌﲏ)(many formsﺑﺎﻹﻧﻜﻠﻴﺰﻳﺔ ،ﺗﻌﺪﺩﻳﺔ ﺍﻷﺷﻜﺎﻝ ﺗﻌﲏ
ﺃﻧﻚ ﺗﻘﻮﻡ ﺑﺈﺳﺘﺪﻋﺎﺀ ﻣﻨﻬﺞ ،ﺗﻨﺴﺒﺔ ﳌﺘﺤﻮﻝ ،ﻭﻟﻜﻦ ﻣﺎﻫﻮ ﺍﳌﻨﻬﺞ ﺍﻟﺬﻱ ﻗﺎﻣﺖ ﺩﻟﻔﻲ ﻓﻌﻠﻴﺎ ﺑﺈﺳﺘﺪﻋﺎﺀﺓ ﻓﺈﻥ ﺫﻟﻚ ﻳﻌﺘﻤﺪ ﻋﻠﻰ
ﳕﻂ ﺍﻟﻐﺮﺽ ﺍﻟﺬﻱ ﻧﺴﺐ ﺇﻟﻴﺔ ﺍﳌﺘﻐﻴﲑ ،ﻭﺩﻟﻔﻲ ﻟﻦ ﺗﺴﺘﻄﻴﻊ ﲢﺪﻳﺪ ﺻﻨﻒ ﻏﺮﺽ ﻫﺬﺍ ﺍﳌﺘﻐﲑ ﺣﱴ ﻭﻗﺖ ﺍﻟﺘﺸﻐﻴﻞ .
ﻣﻴﺰﺓ ﺗﻌﺪﺩﻳﺔ ﺍﻷﺷﻜﺎﻝ ﺃﺎ ﺗﺴﻤﺢ ﺑﻜﺘﺎﺑﺔ ﺃﻛﻮﺍﺩ ﺃﺑﺴﻂ ،ﻭﺍﻟﺘﻌﺎﻣﻞ ﻣﻊ ﺃﻏﺮﺍﺽ ﻣﺘﺒﺎﻳﻨﺔ ﺍﻟﻨﻤﻂ ﻛﻤﺎ ﻟﻮﺃﺎ ﻣﺘﺸﺎﻪ ﲝﻴﺚ ﻳﺘﻢ
ﺍﳊﺼﻮﻝ ﻋﻠﻰ ﺍﻟﺘﺼﺮﻑ ﺍﳌﻨﺎﺳﺐ ﰲ ﺯﻣﻦ ﺍﻟﺘﺸﻐﻴﻞ .
ﻟﺘﻮﺿﻴﺢ ﺫﻟﻚ ﺩﻋﻨﺎ ﻋﻠﻰ ﺳﺒﻴﻞ ﺍﳌﺜﺎﻝ ﻧﻔﺘﺮﺽ ﺃﻥ ﺻﻨﻒ ﻣﺎ ﻭﺻﻨﻒ ﻣﺸﺘﻖ ﻣﻨﻪ ﻳﻌﺮﻓﺎﻥ ﻧﻔﺲ ﺍﳌﻨﻬﺞ ،ﻭﳍﺬﺍ ﺍﳌﻨﻬﺞ ﲢﺪﻳﺪ
ﻣﺘﺄﺧﺮ ،ﻣﺜﻼ ﺍﻟﺼﻨﻔﺎﻥ Tanimalﻭ Tdogﻳﻌﺮﻑ ﻛﻞ ﻣﻨﻬﻤﺎ ﺍﳌﻨﻬﺞ Voiceﻭﺍﻟﺬﻱ ﳜﺮﺝ ﺻﻮﺕ ﺍﳊﻴﻮﺍﻥ ﺍﳌﺨﺘﺎﺭ ،
ﻓﺈﺫﺍ ﻋﺮﻓﻨﺎ ﺍﳌﺘﻐﲑ MyAnimalﻭﺍﻟﺬﻱ ﺳﻴﺸﲑ ﰲ ﺯﻣﻦ ﺍﻟﺘﺸﻐﻴﻞ ﺇﻣﺎ ﻟﻐﺮﺽ ﻣﻦ ﺍﻟﻨﻮﻉ Tanimalﺃﻭ ﻟﻐﺮﺽ ﻣﻦ ﺍﻟﻨﻮﻉ Tdog
،ﺑﺎﻟﺘﺎﱄ ﻓﺈﻥ ﺍﳌﻨﻬﺞ ﺍﻟﺬﻱ ﺳﻴﺘﻢ ﺇﺳﺘﺪﻋﺎﺀﺓ ﻓﻌﻠﻴﺎ ﻳﺘﻢ ﲢﺪﻳﺪﺓ ﻭﻗﺖ ﺍﻟﺘﺸﻐﻴﻞ ﺇﺫﺍ ﻛﺎﻥ ﻣﻨﻬﺞ Voiceﺍﳋﺎﺹ ﺏ Tanimalﺃﻭ
Voiceﺍﳋﺎﺹ ﺏ ، Tdogﺣﺴﺐ ﺍﻟﻨﻤﻂ ﺍﻟﺬﻱ ﻳﺸﲑ ﺇﻟﻴﺔ . MyAnimal
OverRide ﻟﺘﺤﻘﻴﻖ ﺫﻟﻚ ﻧﻌﺮﻑ ﺍﳌﻨﻬﺞ Voiceﻋﻠﻰ ﺷﻜﻞ ) Virtualﺇﻓﺘﺮﺍﺿﻲ( ﰲ ﺍﻟﺼﻨﻒ ﺍﻷﺳﺎﺳﻲ ،ﻭﻋﻠﻰ ﺷﻜﻞ
)ﻣﻬﻴﻤﻦ( ﰲ ﺍﻟﺼﻨﻒ ﺍﳌﺸﺘﻖ ،ﺑﺈﺳﺘﺨﺪﺍﻡ ﺍﻟﻜﻠﻤﺘﺎﻥ ﺍﳌﻔﺘﺎﺣﻴﺘﺎﻥ virtualﻭ . override
Type
Tanimal = class
public
;function Voice: string; virtual
٣٦
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﻓﺈﺫﺍ ﻋﺮﻓﻨﺎ ﺍﳌﺘﻐﲑ MyAnimalﻣﻦ ﺍﻟﺼﻨﻒ Tanimalﻓﺈﻥ ﻧﺴﺘﻄﻴﻊ ﺑﻨﺎﺀﺓ ﻛﻐﺮﺽ ﻣﻦ Tanimalﺃﻭ ، Tdogﺣﺴﺐ
ﻗﻮﺍﻋﺪ ﺍﻟﺘﻮﺍﻓﻖ ﺑﲔ ﺍﻷﳕﺎﻁ ﺍﻟﱵ ﺭﺃﻳﻨﺎﻫﺎ ﰲ ﺍﻟﻔﻘﺮﺓ ﺍﻟﺴﺎﺑﻘﺔ ﻭﺑﺎﻟﺘﺎﱄ ﻧﺴﺘﻄﻴﻊ ﺇﺳﺘﺪﻋﺎﺀ ﻛﻼ ﻣﻦ :
;MyAnimal := Tdog.Create
;MyAnimal := Tanimal.Create
ﻭﺑﺎﻟﺘﺎﱄ ﻓﺈﻧﻨﺎ ﻧﺴﺘﻄﻴﻊ ﰲ ﺯﻣﻦ ﺍﻟﺘﺸﻐﻴﻞ ﺃﻥ ﻧﺸﲑ ﺇﱃ ﻏﺮﺽ ﻣﻦ ﺍﻟﺼﻨﻒ Tdogﺃﻭ ﻣﻦ ﺍﻟﺼﻨﻒ Tanimalﻭﻛﻞ ﻣﻨﻬﻤﺎ ﻟﻪ
ﺍﳌﻨﻬﺞ ، Voiceﻭﻋﻨﺪﻣﺎ ﳓﺎﻭﻝ ﺇﺳﺘﺪﻋﺎﺀ ﻫﺬﺍ ﺍﳌﻨﻬﺞ ﻣﻦ ﺍﻟﻐﺮﺽ MyAnimalﺍﻟﺬﻱ ﻗﺪ ﻳﺸﲑ ﺇﱃ ﺃﻱ ﻣﻨﻬﻤﺎ ،ﻓﺈﻥ ﺗﺼﺮﻑ
ﻣﺘﺮﺟﻢ ﺍﻟﻠﻐﺔ Compilerﻳﻜﻮﻥ ﳐﺘﻠﻔﺎ ﻋﻦ ﺍﳊﺎﻟﺔ ﺍﻟﺴﺎﻛﻨﺔ ﻟﻺﺳﺘﺪﻋﺎﺀ ﺍﻟﱵ ﻳﺘﻢ ﲢﺪﻳﺪ ﻓﻴﻬﺎ ﻋﻨﻮﺍﻥ ﺍﻹﺳﺘﺪﻋﺎﺀ ﺳﻠﻔﺎ ،ﻭﺳﻴﻌﺘﻤﺪ
ﻋﻠﻰ ﻧﻮﻉ ﺍﻟﻐﺮﺽ ﺍﳊﺎﱄ ﻟﺘﺤﺪﻳﺪ ﺃﻱ ﻣﻨﻬﺞ ﳚﺐ ﺃﻥ ﻳﺴﺘﺪﻋﻲ :
;MyAnimal := Tdog.Create
// OR ..
;MyAnimal := Tanimal.Create
ﺇﻥ ﺫﻟﻚ ﳛﺪﺙ ﻓﻘﻂ ﻹﻥ ﺍﳌﻨﻬﺞ ﺇﻓﺘﺮﺍﺿﻲ Virtualﻛﻤﺎ ﻋﺮﻓﻨﺎﺓ ،ﻭﺑﻜﻠﻤﺔ ﺃﺧﺮﻯ ﻓﺈﻥ ﻫﺬﺍ ﺍﻹﺳﺘﺪﻋﺎﺀ ﻟـ
MyAnimal.Voiceﻣﺘﻮﺍﻓﻖ ﻣﻊ ﻛﻞ ﺍﻷﺻﻨﺎﻑ ﺍﳌﺴﺘﻘﺒﻠﻴﺔ ﺍﳌﺸﺘﻘﻪ ﻣﻦ ﺍﻟﺼﻨﻒ ، Tanimalﺣﱴ ﺍﻟﱵ ﱂ ﺗﺘﻢ ﻛﺘﺎﺑﺘﻬﺎ ﺑﻌﺪ .
ﻣﻼﺣﻈﺔ :
ﻫﺬﺍ ﻫﻮ ﺍﻟﺴﺒﺐ ﺍﻟﺘﻘﲏ ﻟﻜﻮﻥ ﺍﻟﱪﳎﺔ ﻏﺮﺿﻴﺔ ﺍﻟﺘﻮﺟﺔ ﺗﻔﻀﻞ ﺍﻟﻘﺪﺭﺓ ﻋﻠﻰ ﺍﻟﺘﻮﺳﻊ ﻭ ﺇﻋﺎﺩﺓ ﺍﻹﺳﺘﻌﻤﺎﻝ ) ، (reusabilityﺣﻴﺚ
ﺃﻧﻚ ﺗﺴﺘﻄﻴﻊ ﻛﺘﺎﺑﺔ ﺷﻔﺮﺍﺕ ﺗﺴﺘﺨﺪﻡ ﺃﺻﻨﺎﻑ ﻣﻦ ﺑﻨﻴﺔ ﻭﺭﺍﺛﻴﺔ ﻣﻌﻘﺪﺓ ﺩﻭﻥ ﺃﻱ ﻣﻌﺮﻓﺔ ﺑﺎﻷﺻﻨﺎﻑ ﺍﶈﺪﺩﺓ ﺍﻟﱵ ﺗﺸﻜﻞ ﺟﺰﺀ ﻣﻦ
ﻫﺬﺓ ﺍﻟﺒﻨﻴﺔ ،ﻭﺑﻜﻠﻤﺔ ﺃﺧﺮﻯ ﺗﺒﻘﻰ ﻫﺬﺓ ﺍﻟﺒﻨﻴﺔ ﺍﻟﻮﺭﺍﺛﻴﺔ ﻭﺑﺮﺍﳎﻚ ﺍﻟﱵ ﺗﺴﺘﺨﺪﻡ ﻫﺬﺓ ﺍﻟﺒﻨﻴﺔ ﻗﺎﺑﻠﺔ ﻟﻠﺘﻮﺳﻊ ﻭﺍﻟﺘﻐﻴﲑ ،ﺣﱴ ﺑﻮﺟﻮﺩ
ﺁﺍﻻﻑ ﺍﻟﺴﻄﻮﺭ ﻣﻦ ﺍﻟﺸﻔﺮﺓ ﺍﻟﱵ ﺗﺴﺘﺨﺪﻣﻬﺎ .ﻭﻟﻜﻦ ﺑﺸﺮﻁ ﻭﺍﺣﺪ ﺃﺳﺎﺳﻲ :ﺃﻥ ﻳﻜﻮﻥ ﺍﻟﺼﻨﻒ ﺍﻟﺴﻠﻒ ﳍﺬﺓ ﺍﻟﺸﺠﺮﺓ
ﺍﻟﻮﺭﺍﺛﻴﺔ ﻣﺼﻤﻢ ﺑﻌﻨﺎﻳﺔ ﻓﺎﺋﻘﺔ .
٣٧
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﻛﻤﺎ ﺭﺃﻳﻨﺎ ،ﳉﻌﻞ ﻣﻨﻬﺞ ﻣﺘﺄﺧﺮ ﺍﻟﺘﺤﺪﻳﺪ ﻣﻬﻴﻤﻨﺎ ﰲ ﺻﻨﻒ ﻣﺸﺘﻖ ﻧﻘﻮﻡ ﺑﺈﺳﺘﺨﺪﺍﻡ ﺍﻟﻜﻠﻤﺔ ﺍﳌﻔﺘﺎﺣﻴﺔ ، overrideﺗﺬﻛﺮ ﺃﻧﻚ
ﺫﻟﻚ ﳝﻜﻦ ﺃﻥ ﳛﺪﺙ ﻓﻘﻂ ﺇﺫﺍ ﻛﺎﻥ ﺍﳌﻨﻬﺞ ﻣﻌﺮﻓﺎ ﻛﻤﻨﻬﺞ ﺇﻓﺘﺮﺍﺿﻲ ) (virtualﰲ ﺍﻟﺼﻨﻒ ﺍﻟﺴﻠﻒ ،ﺃﻱ ﺩﻳﻨﺎﻣﻴﻜﻲ
) (Dynamicﺃﻣﺎ ﺇﺫﺍ ﻛﺎﻥ ﻣﻌﺮﻓﺎ ﻛﻤﻨﻬﺞ ﺳﺎﻛﻦ ) (staticﻓﻼ ﺗﻮﺟﺪ ﻃﺮﻳﻘﺔ ﻋﻨﺪﻫﺎ ﻟﺘﻔﻌﻴﻞ ﺍﻟﺘﺤﺪﻳﺪ ﺍﳌﺘﺄﺧﺮ )(late binding
ﺇﻻ ﺑﺘﻐﻴﲑ ﺷﻔﺮﺓ ﺍﻟﺼﻨﻒ ﺍﻟﺴﻠﻒ ﻧﻔﺴﻬﺎ .
ﻗﻮﺍﻋﺪ ﻫﺬﺓ ﺍﻟﻌﻤﻠﻴﺔ ﻟﻴﺴﺖ ﺻﻌﺒﺔ :ﺍﳌﻨﻬﺞ ﺍﳌﻌﺮﻑ ﻛﻤﻨﻬﺞ ﺳﺎﻛﻦ ) (Staticﺳﻴﺒﻘﻰ ﺳﺎﻛﻨﺎ ﰲ ﻛﻞ ﺍﻷﺻﻨﺎﻑ ﺍﳌﻮﺭﺛﺔ ،ﺣﱴ
ﺗﻘﻮﻡ ﺑﺈﺧﻔﺎﺋﺔ ﲟﻨﻬﺞ ﺇﻓﺘﺮﺍﺿﻲ ﺟﺪﻳﺪ ﳛﻤﻞ ﻧﻔﺲ ﺍﻹﺳﻢ .ﺍﳌﻨﻬﺞ ﺍﳌﻌﺮﻑ ﻛﻤﻨﻬﺞ ﺇﻓﺘﺮﺍﺿﻲ ) (Vertioalﻳﺒﻘﻰ ﻣﺘﺄﺧﺮ ﺍﻟﺘﺤﺪﻳﺪ
ﰲ ﻛﻞ ﺍﻷﺻﻨﺎﻑ ﺍﳌﻮﺭﺛﺔ )ﺇﻻ ﺇﺫﺍ ﻗﻤﺖ ﺑﺈﺧﻔﺎﺋﺔ ﲟﻨﻬﺞ ﺳﺎﻛﻦ ،ﻭﺫﻟﻚ ﻳﻌﺘﱪ ﻋﻤﻼ ﻏﺒﻴﺎ ﺟﺪﺍ ( .ﻻﺗﻮﺟﺪ ﻃﺮﻳﻘﺔ ﻟﺘﻐﻴﲑ ﻫﺬﺍ
ﺍﻟﺘﺼﺮﻑ ،ﻹﻥ ﺍﳌﺘﺮﺟﻢ ﺳﻴﻮﻟﺪ ﺷﻔﺮﺓ ﳐﺘﻠﻔﺔ ﻣﻦ ﺃﺟﻞ ﻣﻨﺎﻫﺞ ﺍﻟﺘﺤﺪﻳﺪ ﺍﳌﺘﺄﺧﺮ .
ﻹﻋﺎﺩﺓ ﺗﻌﺮﻳﻒ ﻣﻨﻬﺞ ﺳﺎﻛﻦ ،ﺃﺿﻒ ﺗﻌﺮﻳﻒ ﺍﳌﻨﻬﺞ ﰲ ﺍﻟﺼﻨﻒ ﺍﳌﺸﺘﻖ ﺑﺪﻭﻥ ﺃﻱ ﺇﺿﺎﻓﺎﺕ ،ﻭﺑﺈﻣﻜﺎﻧﺔ ﺃﻥ ﳝﻠﻚ ﺑﺎﺭﻣﺘﺮﺍﺕ
ﳐﺘﻠﻔﺔ ﻋﻦ ﺍﳌﻨﻬﺞ ﺍﻷﺻﻞ ﰲ ﻫﺬﺓ ﺍﳊﺎﻟﺔ .ﳉﻌﻞ ﻣﻨﻬﺞ ﺇﻓﺘﺮﺍﺿﻲ ﻣﺎ ﻣﻨﻬﺠﺎ ﻣﻬﻴﻤﻨﺎ ،ﳚﺐ ﺃﻥ ﺗﺴﺘﺨﺪﻡ ﺍﻟﻜﻠﻤﺔ ﺍﳌﻔﺘﺎﺣﻴﺔ
، overrideﻭﰲ ﻫﺬﺓ ﺍﳊﺎﻟﺔ ﳚﺐ ﺃﻥ ﳝﻠﻚ ﺍﳌﻨﻬﺞ ﻧﻔﺲ ﺑﺎﺭﻣﺘﺮﺍﺕ ﺍﳌﻨﻬﺞ ﺍﻷﺻﻞ .
type
TmyClass = class
;procedure One; virtual
}procedure Two; {static method
;end
ﺗﺴﺘﻄﻴﻊ ﺟﻌﻞ ﻣﻨﻬﺞ ﻣﺎ ﻣﻬﻴﻤﻨﺎ ﺑﻄﺮﻳﻘﺘﲔ :ﺍﻷﻭﱃ ﻫﻲ ﺇﺳﺘﺒﺪﺍﻝ ﻣﻨﻬﺞ ﺍﻟﺼﻨﻒ ﺍﻷﺻﻞ ﺑﻮﺍﺣﺪ ﺟﺪﻳﺪ .
ﺍﻟﺜﺎﻧﻴﺔ ﻫﻲ ﺇﺿﺎﻓﺔ ﺷﻔﺮﺍﺕ ﺇﺿﺎﻓﻴﺔ ﺇﱃ ﺍﳌﻨﻬﺞ ﺍﳌﻮﺟﻮﺩ ،ﻭﻟﺘﺤﻘﻴﻖ ﺫﻟﻚ ﻧﺴﺘﺨﺪﻡ ﺍﻟﻜﻠﻤﺔ ﺍﳌﻔﺘﺎﺣﻴﺔ inheritedﻹﺳﺘﺪﻋﺎﺀ
ﺍﳌﻨﻬﺞ ﺍﳋﺎﺹ ﺑﺎﻟﺼﻨﻒ ﺍﻷﺻﻞ ﺿﻤﻦ ﺷﻔﺮﺓ ﻣﻨﻬﺞ ﺍﻟﺼﻨﻒ ﺍﳌﺸﺘﻖ .
;procedure TmyDerivedClass.One
begin
// new code
…
;inherited One // call inherited procedure MyClass.One
;end
٣٨
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﻧﺴﺘﻄﻴﻊ ﰲ ﺩﻟﻔﻲ ﺗﻔﻌﻴﻞ ﺍﻟﺘﺤﺪﻳﺪ ﺍﳌﺘﺄﺧﺮ ﺑﻄﺮﻳﻘﺘﲔ .ﺇﻣﺎ ﺗﻌﺮﻳﻒ ﺍﳌﻨﻬﺞ ﻛﻤﻨﻬﺞ ﺇﻓﺘﺮﺍﺿﻲ ﻛﻤﺎ ﺭﺃﻳﻨﺎ ﺳﺎﺑﻘﺎ ،ﺃﻭ ﺗﻌﺮﻳﻔﺔ
ﻛﻤﻨﻬﺞ ﺩﻳﻨﺎﻣﻴﻜﻲ .ﺍﻟﻌﺒﺎﺭﺓ ﺍﻟﻨﺤﻮﻳﺔ ﻟﻠﻜﻠﻤﺘﺎﻥ ﺍﳌﻔﺘﺎﺣﻴﺘﺎﻥ ) (virtualﻭ ) (dynamicﻫﻲ ﻧﻔﺴﻬﺎ ﲤﺎﻣﺎ ،ﻭﻧﺘﻴﺠﺔ
ﺇﺳﺘﺨﺪﺍﻣﻬﻤﺎ ﻫﻲ ﻧﻔﺴﻬﺎ ﺃﻳﻀﺎ ،ﻭﺍﻹﺧﺘﻼﻑ ﺑﻴﻨﻬﻤﺎ ﻓﻘﻂ ﻫﻮ ﺍﻵﻟﻴﺔ ﺍﻟﺪﺍﺧﻠﻴﺔ ﺍﻟﱵ ﻳﺘﺒﻌﻬﺎ ﺍﳌﺘﺮﺟﻢ ﻟﺘﻨﻔﻴﺬ ﺍﻟﺘﺤﺪﻳﺪ ﺍﳌﺘﺄﺧﺮ .
ﺍﳌﻨﺎﻫﺞ ﺍﻹﻓﺘﺮﺍﺿﻴﺔ ﺗﻌﺘﻤﺪ ﻋﻠﻰ ﺟﺪﻭﻝ ﺍﳌﻨﺎﻫﺞ ﺍﻹﻓﺘﺮﺍﺿﻴﺔ VMTﺃﻭ) ، (virtual method tableﻭﺍﻟﺬﻱ ﳜﺰﻥ ﺿﻤﻨﺔ ﻋﻨﺎﻭﻳﻦ
ﺍﳌﻨﺎﻫﺞ ﰲ ﺍﻟﺬﺍﻛﺮﺓ ،ﻭﻳﺴﻤﻰ ﺃﺣﻴﺎﻧﺎ ، Vtableﺣﻴﺚ ﺳﻴﻘﻮﻡ ﺍﳌﺘﺮﺟﻢ ﺑﺘﻮﻟﻴﺪ ﺷﻔﺮﺓ ﺍﻟﻘﻔﺰ ﺇﱃ ﻋﻨﻮﺍﻥ ﺍﻟﺬﺍﻛﺮﺓ ﺍﳌﺨﺰﻥ ﰲ
ﺍﻟﺴﺠﻞ nﳉﺪﻭﻝ ﺍﳌﻨﺎﻫﺞ ﺍﻹﻓﺘﺮﺍﺿﻴﺔ ،ﺗﺴﻤﺢ ﺟﺪﺍﻭﻝ ﺍﳌﻨﺎﻫﺞ ﺍﻹﻓﺘﺮﺍﺿﻴﺔ ﺑﺘﻨﻔﻴﺬ ﺳﺮﻳﻊ ﻟﻺﺳﺘﺪﻋﺎﺀ ،ﻭﻟﻜﻨﻬﺎ ﺗﺘﻄﻠﺐ ﻣﺪﺧﻼ
ﺧﺎﺻﺎ ﻣﻦ ﺃﺟﻞ ﻛﻞ ﻣﻨﻬﺞ ﺇﻓﺘﺮﺍﺿﻲ ﻟﻜﻞ ﺻﻨﻒ ﻣﺸﺘﻖ ،ﺣﱴ ﻟﻮ ﱂ ﻳﻜﻦ ﺍﳌﻨﻬﺞ ﻣﻬﻴﻤﻨﺎ ) (overriddenﰲ ﺍﻟﺼﻨﻒ ﺍﳌﻮﺭﺙ
.
ﺇﺳﺘﺪﻋﺎﺀﺍﺕ ﺍﳌﻨﺎﻫﺞ ﺍﻟﺪﻳﻨﺎﻣﻴﻜﻴﺔ ﺑﺎﳌﻘﺎﺑﻞ ﺗﻨﺠﺰ ﺑﺈﺳﺘﺨﺪﺍﻡ ﺭﻗﻢ ﻓﺮﻳﺪ ﳛﺪﺩ ﺍﳌﻨﻬﺞ ،ﻭﻳﻜﻮﻥ ﳐﺰﻧﺎ ﰲ ﺍﻟﺼﻨﻒ ﻓﻘﻂ ﰲ ﺣﺎﻝ
ﻛﺎﻥ ﻣﻌﺮﻓﺎ ﻓﻴﺔ ﺃﺻﻼ ﺃﻭ ﻛﺎﻥ ﻣﻨﻬﺠﺎ ﻣﻬﻴﻤﻨﺎ ،ﺍﻟﺒﺤﺚ ﻋﻦ ﺍﳌﻨﻬﺞ ﺍﳌﻄﺎﺑﻖ ﻳﻜﻮﻥ ﻋﺎﺩﺓ ﺃﺑﻄﺄ ﻣﻦ ﺍﻟﺒﺤﺚ ﲞﻄﻮﺓ ﻭﺍﺣﺪﺓ ﰲ
ﺟﺪﻭﻝ ﺍﳌﻨﺎﻫﺞ ﺍﻹﻓﺘﺮﺍﺿﻴﺔ ﺍﻟﺴﺎﺑﻖ ،ﻭﺍﳌﻴﺰﺓ ﺍﻷﺳﺎﺳﻴﺔ ﻟﻪ ﺃﻥ ﺍﳌﻨﺎﻫﺞ ﺍﻟﺪﻳﻨﺎﻣﻴﻜﻴﺔ ﺗﻮﻟﺪ ﰲ ﺍﻷﺻﻨﺎﻑ ﺍﳌﺸﺘﻘﻪ ﻓﻘﻂ ﻋﻨﺪﻣﺎ ﻳﻜﻮﻥ
ﻣﻨﻬﺞ ﺍﻟﺼﻨﻒ ﺍﳌﺸﺘﻖ ﻣﻬﻴﻤﻨﺎ .
ﻓﻜﺮﺓ :ﺍﳌﻨﺎﻫﺞ ﺍﳌﺘﺄﺧﺮﺓ ﺍﻟﺘﺤﺪﻳﺪ ﳝﻜﻦ ﺃﻥ ﺗﺴﺘﺨﺪﻡ ﳌﻌﺎﳉﺔ ﺭﺳﺎﺋﻞ ﻭﻳﻨﺪﻭﺯ ،ﻭﻫﺬﺓ ﺍﻟﺘﻘﻨﻴﺔ ﳝﻜﻦ ﺃﻥ ﺗﻜﻮﻥ ﻣﻔﻴﺪﺓ ﺟﺪﺍ
ﳌﱪﳎﻲ ﻭﻳﻨﺪﻭﺯ ﺍﻟﺬﻳﻦ ﳝﻠﻜﻮﻥ ﺍﳋﱪﺓ ﺍﻟﻜﺎﻣﻠﺔ ﺑﺮﺳﺎﺋﻞ ﻭﻳﻨﺪﻭﺯ ﻭﺗﻮﺍﺑﻊ . API
ﻣﻼﺣﻈﺔ :
ﻛﺬﻟﻚ ﺗﺴﺘﺨﺪﻡ ﺍﻟﻜﻠﻤﺔ ﺍﳌﻔﺘﺎﺣﻴﺔ Abstractﻟﻠﺘﺼﺮﻳﺢ ﻋﻦ ﻣﻨﺎﻫﺞ ﺳﺘﻌﺮﻑ ﻓﻘﻂ ﰲ ﺍﻷﺻﻨﺎﻑ ﺍﳌﺸﺘﻘﺔ ﻣﻦ ﺍﻟﺼﻨﻒ ﺍﳊﺎﱄ ،
ﻭﺍﻟﻔﺮﻕ ﺑﻴﻨﻬﺎ ﻭﺑﲔ ﺍﳌﻨﺎﻫﺞ ﺍﻹﻓﺘﺮﺍﺿﻴﺔ ﺃﻧﻪ ﳚﺐ ﺗﻌﺮﻳﻔﻬﺎ ﰲ ﻛﻞ ﺍﻷﺻﻨﺎﻑ ﺍﳌﺸﺘﻘﺔ .ﻣﺜﻼ ﺇﺫﺍ ﻛﺎﻥ ﺍﻟﺼﻨﻒ Tanimalﳝﻠﻚ
ﺍﳌﻨﻬﺞ ﺍﻹﻓﺘﺮﺍﺿﻲ Voiceﻓﺈﻥ ﺃﻱ ﺻﻨﻒ ﻣﺸﺘﻖ ﻣﻨﻪ ﳝﻜﻨﺔ ﺃﻥ ﻳﻌﺮﻑ ﻣﻨﻬﺞ Voiceﺧﺎﺹ ﺑﻪ ،ﺃﻣﺎ ﺇﺫﺍ ﻛﺎﻥ ﳝﻠﻚ ﺍﳌﻨﻬﺞ
Voiceﻛﻤﻨﻬﺞ ﻣﺴﺘﺨﻠﺺ ) (Abstractﻓﺈﻧﺔ ﻳﺘﻮﺟﺐ ﻋﻠﻰ ﻛﻞ ﺻﻨﻒ ﻣﺸﺘﻖ ﺇﻋﺎﺩﺓ ﺗﻌﺮﻳﻔﻪ .
٣٩
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﻟﻘﺪ ﺗﻜﻠﻤﻨﺎ ﰲ ﺍﻟﻔﻘﺮﺍﺕ ﺍﻟﺴﺎﺑﻘﺔ ﻋﻦ ﺗﻮﺍﻓﻘﻴﺔ ﺍﻷﳕﺎﻁ ﰲ ﺩﻟﻔﻲ ،ﻭﺇﻣﻜﺎﻧﻴﺔ ﻧﺴﺐ ﺃﺻﻨﺎﻑ ﻣﺸﺘﻘﺔ ﺇﱃ ﺃﺻﻨﺎﻓﻬﺎ ﺍﳉﺬﺭ ﺑﺪﻭﻥ
ﻣﺸﺎﻛﻞ .ﺣﺴﻨﺎﹰ ..
Tdog ﺃﺳﺘﻄﻴﻊ ﺃﻥ ﺃﻧﺴﺐ Tdogﺇﱃ ﻣﺘﺤﻮﻝ ﻣﻦ ﺍﻟﺼﻨﻒ ﺍﻷﺏ Tanimalﻛﻤﺎ ﺭﺃﻳﻨﺎ ﺳﺎﺑﻘﺎ .ﻟﻜﻦ ﻟﻨﻔﺮﺽ ﺃﻥ ﻟﻠﺼﻨﻒ
ﻣﻨﻬﺞ ﺟﺪﻳﺪ ﻫﻮ Eatﻣﺜﻼ ،ﺇﺫﺍ ﻗﻤﺖ ﺑﺎﻟﻨﺴﺐ ﺍﻟﺴﺎﺑﻖ ﻭﻗﺒﻞ ﺍﳌﺘﻐﲑ ﻣﻦ ﺍﻟﻨﻮﻉ Tanimalﺃﻥ ﻳﺪﻝ ﻋﻠﻰ ﺍﻟﻐﺮﺽ ﻣﻦ ﺍﻟﻨﻮﻉ
TDogﻳﻔﺘﺮﺽ ﺃﻥ ﺃﺳﺘﻄﻴﻊ ﺇﺳﺘﺪﻋﺎﺀ ﺍﳌﻨﻬﺞ Eatﺍﳋﺎﺹ ﺏ .. ، Tdogﻭﻟﻜﻦ ﺫﻟﻚ ﻟﻦ ﳛﺪﺙ ﰲ ﺍﳊﻘﻴﻘﺔ ،ﻹﻥ ﺍﳌﺘﺤﻮﻝ
ﻻﺯﺍﻝ ﻣﻦ ﺍﻟﺼﻨﻒ Tanimalﻭﺍﻟﻌﻤﻠﻴﺔ ﺑﺮﻣﺘﻬﺎ ﻫﻲ ﺃﻥ ﺍﳌﺘﺤﻮﻝ ﻗﺒﻞ ﺃﻥ ﳛﺘﻮﻱ ﻏﺮﺽ Tdogﻟﻜﻨﺔ ﻏﲑ ﻗﺎﺩﺭ ﻋﻠﻰ ﺗﻠﺒﻴﺔ ﻛﺎﻓﺔ
ﻣﺘﻄﻠﺒﺎﺕ ) Tdogﺍﻟﻐﲑ ﻣﻮﺟﻮﺩﺓ ﰲ Tanimalﺃﺻﻼ ( .
ﳊﻞ ﻫﺬﺍ ﺍﻹﺷﻜﺎﻝ ﻧﺴﺘﻄﻴﻊ ﺇﺳﺘﺨﺪﺍﻡ ﺗﻘﻨﻴﺔ ﻣﻦ ﺗﻘﻨﻴﺎﺕ ، (run-time type information) RTTIﻭﺍﻟﱵ ﺗﻌﺘﻤﺪ ﻋﻠﻰ ﻓﻜﺮﺓ
ﺃﻥ ﻛﻞ ﻏﺮﺽ ﻳﻌﺮﻑ ﻣﺎﻫﻮ ﳕﻄﺔ ﻭﻣﺎﻫﻮ ﺍﻟﺼﻨﻒ ﺍﻷﺏ ﻟﻪ .
ﺗﺴﺘﻄﻴﻊ ﺍﻟﺴﺆﺍﻝ ﻋﻦ ﻫﺬﺓ ﺍﳌﻌﻠﻮﻣﺎﺕ ﺑﺈﺳﺘﺨﺪﺍﻡ ﺍﳌﻌﺎﻣﻞ ، ISﺍﻟﺸﺒﻴﻪ ﺇﱃ ﺣﺪ ﻣﺎ ﺑﺎﳌﺴﺎﻭﺍﺓ )=( .ﺑﺎﺭﺍﻣﺘﺮﺍ isﳘﺎ ﻏﺮﺽ ﻣﻦ
ﺍﻟﻴﺴﺎﺭ ﻭﺻﻨﻒ ﻣﻦ ﺍﻟﻴﻤﲔ ،ﻭﳛﺪﺩ Isﺇﺫﺍ ﻛﺎﻥ ﺍﻟﻐﺮﺽ ﺍﻷﻳﺴﺮ ﻣﻦ ﺍﻟﺼﻨﻒ ﺍﻷﳝﻦ ﺃﻡ ﻻ .
… if MyAnimal is TDog then
ﺍﻵﻥ ﻭﺑﻌﺪ ﺃﻥ ﺗﺄﻛﺪﺕ ﺃﻥ ﺍﻟﺼﻨﻒ ﻫﻮ Tdogﳝﻜﻨﻚ ﺇﺟﺮﺍﺀ ﲢﻮﻳﻞ ﺁﻣﻦ ﻟﻠﺼﻨﻒ Tanimalﺇﱃ Tdogﻛﺎﻵﰐ :
var
;MyDog: TDog
begin
if MyAnimal is TDog then
begin
;)MyDog := TDog (MyAnimal
;Text := MyDog.Eat
;end
ﺑﺈﻣﻜﺎﻧﻨﺎ ﺇﳒﺎﺯ ﻧﻔﺲ ﺍﻟﻌﻤﻠﻴﺔ ﺍﻟﺴﺎﺑﻘﺔ ﺑﺎﳌﻌﺎﻣﻞ ﺍﳍﺎﻡ ﺍﻟﺜﺎﱐ ﺍﻟﺬﻱ ﺗﻮﻓﺮﺓ ﻟﻨﺎ RTTIﻭﻫﻮ ﺍﳌﻌﺎﻣﻞ ، ASﻭﺍﻟﺬﻱ ﻳﻘﻮﻡ ﺑﻌﻤﻠﻴﺔ
ﺍﻟﺘﺤﻮﻳﻞ ﺍﻟﺴﺎﺑﻘﺔ ﻓﻘﻂ ﺇﺫﺍ ﻛﺎﻥ ﺍﻟﺼﻨﻒ ﺍﳌﻄﻠﻮﺏ ﻣﺘﻮﺍﻓﻖ ﻣﻊ ﺍﻟﺼﻨﻒ ﺍﻷﺻﻠﻲ .ﺑﺎﺭﺍﻣﺘﺮﺍ ﺍﳌﻌﺎﻣﻞ ﳘﺎ ﺃﻳﻀﺎ ﻏﺮﺽ ﻳﺴﺎﺭﻱ
ﻭﺻﻨﻒ ﳝﻴﲏ ﻭﺍﻟﻨﺎﺗﺞ ﻫﻮ ﻏﺮﺽ ﰎ ﲢﻮﻳﻠﺔ ﺇﱃ ﺍﻟﺼﻨﻒ ﺍﳉﺪﻳﺪ ﺍﳌﻌﻄﻰ :
;MyDog := MyAnimal as TDog
;Text := MyDog.Eat
٤٠
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﺇﺫﺍ ﻛﻨﺖ ﺗﺮﻳﺪ ﻓﻘﻂ ﺇﺳﺘﺪﻋﺎﺀ Eatﺑﺈﻣﻜﺎﻧﻚ ﺇﺳﺘﺨﺪﺍﻡ ﺣﺎﻟﺔ ﺃﺑﺴﻂ :
;(MyAnimal as TDog).Eat
ﻧﺘﻴﺠﺔ ﺍﻟﺘﻌﺒﲑ ﺳﺘﻜﻮﻥ ﻏﺮﺽ ﻣﻦ ﺍﻟﺼﻨﻒ Tdogﻭﺑﺈﻣﻜﺎﻧﻚ ﺇﺳﺘﺨﺪﺍﻡ ﺇﻱ ﻣﻨﻬﺞ ﻣﻦ ﻫﺬﺍ ﺍﻟﺼﻨﻒ ،ﺍﻟﻔﺎﺭﻕ ﺑﲔ ﺍﻟﺘﺤﻮﻳﻞ
ﺍﻟﺴﺎﺑﻖ ﻭﺍﻟﺘﺤﻮﻳﻞ ﺑﺈﺳﺘﺨﺪﺍﻡ ، asﺃﻥ asﺳﻴﺨﺘﱪ ﺍﻟﻐﺮﺽ ﻭﻳﺮﻓﻊ ﺇﺳﺘﺜﻨﺎﺀ ﺇﺫﺍ ﻛﺎﻥ ﺍﻟﻐﺮﺽ ﻏﲑ ﻣﺘﻮﺍﻓﻖ ﻣﻊ ﺍﻟﺼﻨﻒ ﺍﻟﺬﻱ
ﳓﺎﻭﻝ ﲢﻮﻳﻠﺔ ﺇﻟﻴﺔ ،ﻭﻫﺬﺍ ﺍﻹﺳﺘﺜﻨﺎﺀ ﻫﻮ )" . ("EInvalidCast
ﻟﻜﲏ ﻻ ﺃﺭﻯ ﺩﺍﻉ ﻹﺳﺘﺨﺪﺍﻡ isﻭ asﻭﺭﺍﺀ ﺑﻌﻀﻬﻤﺎ ﻭﺍﻟﻘﻴﺎﻡ ﺑﻌﻤﻠﻴﺔ ﺍﳌﻘﺎﺭﻧﺔ ﻣﺮﺗﲔ .
ﻫﺬﺍﻥ ﺍﳌﻌﺎﻣﻼﻥ ﺃﺳﺎﺳﻴﺎﻥ ﻭ ﻣﻔﻴﺪﺍﻥ ﺟﺪﺍ ﰲ ﺩﻟﻔﻲ ،ﻹﻧﻚ ﻋﺎﺩﺓ ﻣﺎ ﺗﺮﻳﺪ ﻛﺘﺎﺑﺔ ﺷﻔﺮﺓ ﻋﺎﻣﺔ ﺗﺴﺘﺨﺪﻡ ﻣﻦ ﻋﺪﺓ ﻋﻨﺎﺻﺮ ﺑﻨﻔﺲ
ﺍﻟﻄﺮﻳﻘﺔ .
ﺃﻫﻢ ﻣﺜﺎﻝ ﳜﻄﺮ ﺑﺒﺎﱄ ﻫﻮ ﺇﺳﺘﺨﺪﺍﻡ ﺍﳌﺘﺤﻮﻝ ﺍﻟﻮﺳﻴﻄﻲ Senderﰲ ﻛﻞ ﺃﺣﺪﺍﺙ ﺩﻟﻔﻲ Sender ،ﻫﻮ ﻣﺘﺤﻮﻝ ﻣﻦ ﺍﻟﺼﻨﻒ
ﺍﳉﺪ Tobjectﺍﻟﺬﻱ ﻳﻘﺒﻞ ﲨﻴﻊ ﺍﻷﻏﺮﺍﺽ ،ﻭﺑﺎﻟﺘﺎﱄ ﺩﺍﺋﻤﺎ ﲢﺘﺎﺝ ﻟﺮﺩﺓ ﺇﱃ ﺍﻟﻐﺮﺽ ﺍﻷﺻﻠﻲ ﳌﻌﺮﻓﺔ ﻣﻦ ﻫﻮ ﻫﺬﺍ ﺍﻟﻐﺮﺽ ﺍﻟﺬﻱ
ﻃﻠﺐ ﺍﳊﺪﺙ :
ﺇﺎ ﺗﻘﻨﻴﺔ ﺷﺎﺋﻌﺔ ﰲ ﺩﻟﻔﻲ ،ﻭﺗﺴﺘﺨﺪﻡ ﰲ ﻛﺜﲑ ﻣﻦ ﺍﳊﺎﻻﺕ ،ﻣﻌﺎﻣﻼ ﻣﻌﻠﻮﻣﺎﺕ ﳕﻂ ﺯﻣﻦ ﺍﻟﺘﺸﻐﻴﻞ RTTIﻫﺬﻳﻦ ﻗﻮﻳﺎﻥ
ﻟﻠﻐﺎﻳﺔ ،ﻭﻳﻌﺘﱪﺍﻥ ﻣﻦ ﻃﺮﻕ ﺍﻟﱪﳎﺔ ﺍﻟﻘﻴﺎﺳﻴﺔ ﺍﻟﱵ ﺗﺘﺒﻌﻬﺎ ﺑﻮﺭﻻﻧﺪ ﰲ ﺷﻔﺮﺓ ﻋﻨﺎﺻﺮ ، VCLﻭﻟﻜﻦ ﺭﻏﻢ ﺫﻟﻚ ﺗﻮﺟﺪ ﺑﻌﺾ
ﺍﳊﺎﻻﺕ ﺍﳋﺎﺻﺔ ﻟﺘﻔﻀﻴﻞ ﺇﺳﺘﺨﺪﺍﻡ ﻃﺮﻕ ﺃﺧﺮﻯ ﻋﻠﻴﻬﻤﺎ ﻋﻨﺪﻣﺎ ﺗﺮﻳﺪ ﺣﻞ ﻣﺸﻜﻠﺔ ﻣﻌﻘﺪﺓ ﺗﺴﺘﺨﺪﻡ ﺃﺻﻨﺎﻑ ﻣﺘﻨﻮﻋﺔ ﻭﻣﺘﺪﺍﺧﻠﺔ
ﺃﻧﺼﺤﻚ ﺑﺎﻟﻌﻤﻞ ﻣﻊ ﺗﻌﺪﺩﻳﺔ ﺍﻷﺷﻜﺎﻝ ،ﻭﺍﻟﻘﺎﻋﺪﺓ ﺍﻵﻥ ﻫﻲ ﺃﻥ ﻻ ﺗﺴﺘﺨﺪﻡ RTTIﻣﻜﺎﻥ ﺗﻌﺪﺩﻳﺔ ﺍﻷﺷﻜﺎﻝ ،
ﻣﺸﻜﻠﻪ ﺍﻝ RTTIﺃﺎ ﳚﺐ ﺃﻥ ﺗﺴﲑ ﰲ ﺍﻟﺸﺠﺮﺓ ﺍﻟﻮﺭﺍﺛﻴﺔ ﻟﻠﺘﺄﻛﺪ ﻣﻦ ﺃﻥ ﺍﻟﺼﻨﻒ ﻣﻄﺎﺑﻖ .ﺭﲟﺎ ﻳﺴﺒﺐ ﺫﻟﻚ ﺃﺛﺮﺍ ﺳﻴﺌﺎ ﻟﻸﺩﺍﺀ
٤١
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﺗﻜﻤﻦ ﺃﳘﻴﺔ ﺍﻟﻮﺍﺟﻬﺎﺕ ﰲ ﺗﻘﺪﱘ ﺑﻌﺾ ﻣﻴﺰﺍﺕ ﺍﻟﻮﺭﺍﺛﺔ ﺍﳌﺘﻌﺪﺩﺓ ) (multiple inheritanceﺑﺴﻬﻮﻟﺔ ﻭﺑﺪﻭﻥ ﺍﻟﻐﺮﻕ ﰲ
ﺍﻟﺘﻔﺼﻴﻼﺕ ﺍﻟﻨﺤﻮﻳﺔ ﳍﺎ ،ﻛﻤﺎ ﺃﻥ ﻟﻠﻮﺍﺟﻬﺎﺕ ﺃﳘﻴﺔ ﺃﺳﺎﺳﻴﺔ ﻣﻦ ﺃﺟﻞ ﺇﺳﺘﺨﺪﺍﻡ ﳕﺎﺫﺝ ﺍﻷﻏﺮﺍﺽ ﺍﳌﻮﺯﻋﺔ )ﻣﺜﻞ CORBAﻭ
(SOAPﻭﺍﻟﺘﻔﺎﻋﻞ ﻣﻊ ﺃﻏﺮﺍﺽ ﲤﺖ ﻛﺘﺎﺑﺘﻬﺎ ﰲ ﻟﻐﺎﺕ ﺃﺧﺮﻯ C++ﺃﻭ Javaﻣﺜﻼ .
ﻣﻌﻈﻢ ﺍﻟﻠﻐﺎﺕ ﺍﻟﻐﺮﺿﻴﺔ ﺍﻟﺘﻮﺟﺔ ﺍﳊﺪﻳﺜﺔ ،ﻣﻦ Javaﺣﱴ ، C#ﲤﻠﻚ ﻓﻜﺮﺓ ﺍﻟﻮﺍﺟﻬﺎﺕ ﻫﺬﺓ .
ﺇﺫﺍ ﻗﻤﺖ ﺑﺘﻌﺮﻳﻒ ﺻﻨﻒ ﺟﺪﻳﺪ ﻣﻦ ﺃﺟﻞ ﲤﺜﻴﻞ ﺻﻨﻒ ﺁﺧﺮ ﺑﺸﻜﻞ ﳐﺘﺼﺮ ،ﳝﻜﻦ ﳍﺬﺍ ﺍﻹﺧﺘﺼﺎﺭ ﺃﻥ ﻳﺼﻞ ﺇﱃ ﺩﺭﺟﺔ ﺃﻥ
ﺍﻟﺼﻨﻒ ﻳﻘﻮﻡ ﺑﺴﺮﺩ ﳎﻤﻮﻋﺔ ﻣﻦ ﺍﳌﻨﺎﻫﺞ ﻓﻘﻂ ﺣﱴ ﺑﺪﻭﻥ ﺗﻌﺮﻳﻒ ﻹﺟﺴﺎﻡ ﻫﺬﺓ ﺍﳌﻨﺎﻫﺞ ﰲ ﻗﺴﻢ ، Implementation
ﰲ ﻫﺬﻩ ﺍﳊﺎﻟﺔ ﳝﻜﻨﻚ ﺇﺳﺘﺨﺪﺍﻡ ﺗﻘﻨﻴﺔ ﺍﻟﻮﺍﺟﻬﺎﺕ ، Interfacesﻭﻛﺄﻧﻨﺎ ﻧﻌﱪ ﻋﻦ ﻫﺬﺍ ﺍﻟﺼﻨﻒ ﺍﳌﺨﺘﺼﺮ ﺑﻮﺍﺟﻬﺔ ﲢﻮﻱ ﺗﻌﺮﻳﻒ
ﻹﲰﺎﺀ ﺍﳌﻨﺎﻫﺞ ﺍﻟﱵ ﳝﻜﻦ ﺇﺳﺘﺨﺪﺍﻣﻬﺎ .
-ﺍﻷﻏﺮﺍﺽ ﻣﻦ ﺍﻟﻨﻤﻂ ﻭﺍﺟﻬﺔ ﲢﺮﺭ ﺗﻠﻘﺎﺋﻴﺎ ﻋﻨﺪ ﺇﻧﺘﻬﺎﺀ ﺍﻟﺼﻼﺕ ﻣﻌﻬﺎ ،ﺑﺸﻜﻞ ﻣﺸﺎﺑﻪ ﳌﻌﺎﳉﺔ ﺍﻟﺴﻼﺳﻞ ﺍﻟﻄﻮﻳﻠﺔ ﺣﻴﺚ
ﺗﻘﻮﻡ ﺩﻟﻔﻲ ﺑﺈﺩﺍﺭﺓ ﺍﻟﺬﺍﻛﺮﺓ ﺑﺎﻟﻜﺎﻣﻞ ﺗﻘﺮﻳﺒﺎ .
-ﻣﻊ ﺃﻥ ﺍﻟﺼﻨﻒ ﳝﻜﻦ ﺃﻥ ﻳﺮﺙ ﺻﻨﻔﺎ ﺃﺳﺎﺳﻴﺎ ﻭﺍﺣﺪﺍ ﻓﻘﻂ ،ﻟﻜﻨﺔ ﳝﻜﻦ ﺃﻥ ﳝﺜﻞ ﺃﻛﺜﺮ ﻣﻦ ﻭﺍﺟﻬﻪ ﻣﻌﺎ .
٤٢
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
]'}['{GUID
memberList
;end
ﻣﺜﻼ :
type
ICanFly = interface
]'}['{EAD9C4B4-E1C5-4CF4-9FA0-3B812C880A21
;function Fly: string
;end
GUIDﺇﺧﺘﺼﺎﺭ ﻟـ) (Globally Unique Identifierﻫﻮ ﺭﻗﻢ ﻣﻌﺮﻑ ﻳﺴﺘﺨﺪﻡ ﻟﺘﻌﺮﻳﻒ ﺍﻟﻮﺍﺟﻬﺔ ﺑﺸﻜﻞ ﻓﺮﻳﺪ .
ﺗﺴﺘﻄﻴﻊ ﺗﻌﺮﻳﻒ ﻫﺬﺍ ﺍﻟﺮﻗﻢ ﺗﻠﻘﺎﺋﻴﺎ ﺑﻀﻐﻂ Ctrl+Shift+Gﰲ ﳏﺮﺭ ﺩﻟﻔﻲ .
ﻛﻤﺎ ﺗﻼﺣﻆ ﻓﺈﻥ ﺗﻌﺮﻳﻒ ﺍﻟﻮﺍﺟﻬﻪ ﺷﺒﻴﺔ ﺑﺘﻌﺮﻳﻒ ﺍﻟﺼﻨﻒ ﰲ ﻛﺜﲑ ﻣﻦ ﺍﳊﺎﻻﺕ ،ﻭﻟﻜﻦ ﺗﻮﺟﺪ ﺑﻌﺾ ﺍﻟﻔﺮﻭﻗﺎﺕ ﻟﻮﺿﻌﻬﺎ
ﰲ ﺍﳊﺴﺒﺎﻥ :
-ﻗﺎﺋﻤﺔ ﺍﻟﻌﻨﺎﺻﺮ )ﺍﻟﱵ ﲰﻴﻨﺎﻫﺎ memberListﰲ ﺍﻟﺸﻜﻞ ﺍﻟﻌﺎﻡ ﻟﻠﺘﻌﺮﻳﻒ( ﳝﻜﻦ ﺃﻥ ﲢﻮﻱ ﻓﻘﻂ ﺇﻣﺎ ﻣﻨﺎﻫﺞ ﺃﻭ ﺧﺼﺎﺋﺺ
.ﺗﻌﺮﻳﻒ ﺣﻘﻮﻝ ﻏﲑ ﻣﺴﻤﻮﺡ ﺑﻪ ﰲ ﺍﻟﻮﺍﺟﻬﺎﺕ .
-ﲟﺎ ﺃﻧﻪ ﻻﺗﻮﺟﺪ ﻟﻠﻮﺍﺟﻬﻪ ﺣﻘﻮﻝ ،ﻓﺈﻥ ﳏﺪﺩﺍﺕ Readﻭ Writeﺍﳋﺎﺻﺘﺎﻥ ﺑﺘﻌﺮﻳﻒ ﺍﳋﺼﺎﺋﺺ ﳚﺐ ﺃﻥ ﻳﻜﻮﻧﺎ
ﻣﻨﺎﻫﺞ ﺣﺘﻤﺎ .
-ﻛﻞ ﻋﻨﺎﺻﺮ ﺍﻟﻮﺍﺟﻬﺔ ﺗﻜﻮﻥ ﻋﺎﻣﺔ ) ، (Publicﻭﻻ ﳎﺎﻝ ﻟﺘﻘﻴﻴﺪ ﺍﻟﺮﺅﻳﺎ .
٤٣
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
IMalloc = interface(IInterface)
['{00000002-0000-0000-C000-000000000046}']
end;
. ﻭﺑﻌﺪﻣﺎ ﺗﻘﻮﻡ ﺑﺘﻌﺮﻳﻒ ﺍﻟﻮﺍﺟﻬﺔ ﺗﺴﺘﻄﻴﻊ ﺗﻌﺮﻳﻒ ﺻﻨﻒ ﻣﻦ ﺃﺟﻞ ﺇﺳﺘﺨﺪﺍﻣﻬﺎ ﺑﻮﺍﺳﺘﻄﺔ
: ﻣﺜﻼ
type
TAirplane = class (TInterfacedObject, ICanFly)
function Fly: string;
end;
ﻃﺮﻳﻘﺔ ﺍﻹﺳﺘﺨﺪﺍﻡ ﻫﻲ ﻧﻔﺴﻬﺎ ﻹﻧﻨﺎ ﻧﺘﻌﺎﻣﻞ، ﺍﻵﻥ ﺃﺻﺒﺤﻨﺎ ﺟﺎﻫﺰﻳﻦ ﻹﺳﺘﺨﺪﺍﻡ ﻏﺮﺽ ﻣﻦ ﻫﺬﺍ ﺍﻟﺼﻨﻒ ﺍﻟﺬﻱ ﳝﺜﻞ ﺍﻟﻮﺍﺟﻬﺔ
: ﻣﻊ ﺻﻨﻒ ﻣﻦ ﺍﻟﻮﺍﺟﻬﺔ ﻭﻟﻴﺲ ﻣﻊ ﺍﻟﻮﺍﺟﻬﺔ ﻣﺒﺎﺷﺮﺓ
var
Flyer1: ICanFly;
begin
Flyer1 := TAirplane.Create;
Flyer1.Fly;
end;
٤٤
ﻋﺮﻭﺓ ﻋﻴﺴﻰ ﺍﻟﱪﳎﺔ ﺍﻟﻐﺮﺿﻴـﺔ ﺍﻟﺘﻮﺟﻪ ﰲ ﺩﻟﻔﻲ
ﺍﳌﺮﺍﺟﻊ :
Mastring Delphiﻟﻠﻤﺆﻟﻒ Marco Cantu