במאמר הקודם ActionScript 3: מבוא למדנו על אובייקטים ו-classים ב-ActionsScript 3. במאמר הזה נמשיך ונפתח את נושא ה-class, נלמד קצת על הורשה ן-interface.
הורשה
במאמר הקודם יצרנו class של human. נניח שאני רוצה ליצור גם class של monkey. באופן עקרוני, שום דבר לא מונע ממני לעשות copy&paste ל-humanClass ולשנות אותה ל-monkeyClass. הרי גם לקוף יש שם, פה, עיניים ומין.
אבל אם ניצור class אב של mammal שבו יש תכונות של פה, עיניים ומין (כמו שיש לכל היונקים) ושה-classים של הקוף והאדם יירשו ממנו את התכונות, זה יחסוך לנו קוד רב. אם נרצה בעתיד להוסיף dogClass נוכל לעשות את זה יותר בקלות.
ראשית, ניצור class של mammal. חשוב מאד להקפיד לשים כל class בקובץ as משלו שנושא את אותו השם! זה קריטי מאד. לפיכך mammalClass יישמר אחר כבוד ב-mammalClass.as ולא בשום מקום אחר.
package
{
public class mammalClass
{
//Properties
protected var mouth:Number = 1;
}
}
בתכל'ס מדובר ב-class הכי פשוט (שלא לומר מטומטם) שיש בעולם. כל מה שיש ב-class הזה זו תכונה אחת של פה. עכשיו ניצור את ה-class של ה-human שיורש את התכונות שלו מה-mammal:
package
{
public class humanClass extends mammalClass //Extends is the inheritance syntax
{
public function talk() // Talk method
{
if(this.mouth == 1) //the mouth property is from mammalClass!
{
trace("Blah Blah Blah"); //"Speak"
}
}
}
}
גם humanClass יישמר אחר כבוד בקובץ as משלו. בקובץ fla אנו נבצע מימוש של class human. ונגרום לו לדבר:
import humanClass; //Name of the ActionScrip file.
var mosheHuman:humanClass = new humanClass();
mosheHuman.talk();
כמה מילים על כימוס (encapsulation). כל מי שמכיר OOP
ולו בצורה שטחית יודע מה זה private, public ו-protected. בניגוד ל-AS2 ששם ההגדרות היו יותר רופפות. ב-AS3 הכל מסודר יותר ו-private הוא אכן private ל-class שלו. אם אנו רוצים שהתכונות/מתודות יעברו הורשה, הן צריכות להיות protected או public. ישנן עוד שתי רמות הרשאה ב-AS3: הראשונה היא internal שמאפשרת גישה למתודות ולתכונות לכל אובייקט שנמצא באותו package והשניה היא namespace. אני לא אכנס נכון לעכשיו לשתיהן.
interface
טוב, הזהרתי מראש שאני הולך לדבר על פולימורפיזם. בקצרה, מדובר ביכולת של class לרשת ממספר מקומות. בעוד שהורשה מספקת לי יכולת לרשת רק class אחד. אני יכול להשתמש ב-interface על מנת לרשת מספר classים. לא מדובר על הורשה 'קלאסית' אלא על הורשת מתודות כלליות בלבד. כך למשל, בוא ונניח שיש לי class של פעולות שאפשר לבצע בנהיגה – לסובב את ההגה, להאיץ ולבלום. הפעולות האלו נכונות לכל כלי רכב שהוא: משאית, טרקטור, ומכונית פרטית. אם אני אאגד את כל הפעולות האלו ב-interface אחד ואבקש מכל class של כלי רכב (מכונית, טרקטור, וכו') ליישם את הממשק הזה. אז אני אוכל להיות בטוח שהפעולות האלו יהיו קיימות בכל class שמיישם אותן. כך יווצר לי קוד עמיד יותר בפני תקלות. כל מה שאני צריך זה ליצור interface של פעולות נהיגה ולהצמיד אותו לכל כלי רכב. ה-class של מכונית יכול לרשת class של 'כלי רכב', ה-class של הטרקטור יכול לרשת class של 'כלי עבודה' אבל פעולות הנהיגה יהיו זהות בכולם בזכות ה-interface.
בואו ונדגים:
ראשית אני יוצר Interface – אוסף פעולות שמשותפות לכל מי שאני רוצה שיישם את ה-interface. במקרה שלנו אני אסתפק ב-3 פעולות. שימו לב שאני לא יכול לשים ב-interface תכונות. רק מתודות. גם אני לא יכול לשים הרבה במתודות האלו מלבד כמה דברים בסיסיים:
package
{
public interface steeringClass
{
function steerWheel(degrees):void;
function breaks():void;
function accelerate():void;
}
}
וכמובן שזה יישמר אחר כבוד ב-steeringClass.as. אחרי שיצרנו את הממשק, בואו וניצור class שנקרא carClass שבו יש כמה תכונות של מכונית (לאו דווקא מכונית פרטית!). זו דוגמא ל-class שממנו נירש.
package
{
public class carClass
{
public var wheels:Number = 4;
public var seats:Number = 5;
public var brand:String = "Opel";
}
}
לא נשכח לשמור אותו במקום המתאים עכשיו ניצור סוף סוף את המכונית שלנו. שימו לב שהיא יורשת גם את התכונות מה-class של carClass וגם חובה שיהיו בה את המתודות שהגדרנו לה ב-interface. אם לא יהיו בה את המתודות האלו. יהיו לנו שגיאות בקוד שמפרטות את העובדה שאין את המתודות. בכך אני מבטיח שיהיו לנו את המתודות האלו.
package
{
public class privateCarClass extends carClass implements steeringClass
{
public function steerWheel(degrees):void // Stirring
{
trace("Steering wheel by " + degrees);
}
public function breaks():void
{
trace("Break");
}
public function accelerate():void
{
if(this.wheels)
{
trace("Accelerate");
}
}
}
}
עכשיו ניצור את ה-fla על מנת שנריץ את הכל:
var myCar:privateCarClass = new privateCarClass ();
myCar.accelerate();
שימו לב שצריך לשמור כל class ו-class בשם שלו!
interface חשובה במיוחד לכתיבת קוד איכותי וגמיש שמסוגל לקבל שינויים.
למרות שאפשר להמשיך עוד ועוד בנוגע לתיאוריה אני חושב שדי בכך. במאמר הבא אנו סוף סוף מלכלכים את הידיים בקוד ממשי ונדגים איך כל התיאוריה שלמדנו במאמר הזה ובקודמו תתממש למציאות תוך כדי לימוד כיצד ליצור shapes. אני ממליץ מאד מאד לנסות את כל הדוגמאות לעיל ולנסות קצת הורשה וקצת interface. לכאורה מדובר בתיאוריה חסרת טעם, אבל זה באמת חשוב להבנת AS3 ואת דרך העבודה העתידית שלנו.