1.28k likes | 1.74k Views
Web Services. תכנות מונחה עצמים - מעשי. ליווי מקצועי : ארז קלר www.corner.co.il. המחלקה ( Encapsulation ). הורשה ( Inheritance ). רב צורתיות ( Polymorphism ) . ממשקים ( Interface ). המחלקה ( Encapsulation ). המחלקה הנה אבן היסוד של תכנות מכוון העצמים.
E N D
Web Services תכנות מונחה עצמים - מעשי ליווי מקצועי : ארז קלר www.corner.co.il
המחלקה (Encapsulation). • הורשה (Inheritance). • רב צורתיות (Polymorphism). • ממשקים (Interface).
המחלקה (Encapsulation) • המחלקה הנה אבן היסוד של תכנות מכוון העצמים. • המחלקה הנה מבנה לוגי מופשט (Abstract), המאגד בתוכו נתונים ופעילויות שניתן לבצע על מופע (Instance) של המחלקה הנקרא אובייקט (Object). • המחלקה ב- C# מממשת את התכונה הראשונה של OOP – הכמסה Encapsulation . • תוכנית ב- C# היא לא יותר מאשר אוסף של מחלקות וקשרים ביניהן.
המחלקה (Encapsulation) public class ClassName { private Type field1; private Type field2; … private Type fieldN; public Method 1() { … } public Method 2() { … } … public Method N() { … } } • תכונות (Data Members) תמיד יהיו Private . • שיטות (Methods) יכולים להיות גם Private וגם Public. • אין חשיבות לסדר הגדרת חברי המחלקה. • שפת C# מגדירה 3 מצייני גישה בנוסף ל- Private ו- Public : • Protected • internal • protected internal. (עליהם נדון בהמשך הקורס)
המחלקה (Encapsulation) קוד המחלקה: דוגמה public class Person { private int m_ID; private string m_LastName; private string m_FirstName; private int m_Age; public Person() { . . . } public Person(int id) { . . . } public SetPerson(. . .) { . . . } public void Print() { . . . } public WriteToFile() { . . . } public ReadFromFile() { . . . } . . . } כותרת המחלקה ,תכונות המחלקה Data Member שיטות בונות - Constructor שיטות המחלקה
המחלקה (Encapsulation) קוד המחלקה: תכונות המחלקה מתארות את האובייקט. בדוגמה: התכונות מתארות את פרטי אדם, שם פרטי שם משפחה ת"ז וכו'. public class Person { private int m_ID; private string m_LastName; private string m_FirstName; private int m_Age; . . . }
המחלקה (Encapsulation) קוד המחלקה: שיטות המחלקה מגדירות את ההתנהגות של האובייקט. בדוגמה: האובייקט מגדיר התנהגות של הדפסה, שינוי פרטים,כתיבה וקריאה מקבצים. public class Person { . . . public Person() { . . . } public Person(int id) { . . . } public SetPerson(. . .) { . . . } public void Print() { . . . } public WriteToFile() { . . . } public ReadFromFile() { . . . } . . . }
המחלקה (Encapsulation) דוגמה נוספת: המחלקה Point מייצגת נקודה במרחב, המחלקה מספקת את כל הפונקציונאליות הנדרשת. כותרת המחלקה public class Point { private intm_X; private intm_Y; public Point (intx, inty) { . . . } public void Print() { . . . } public Point SetPoint(Point p) {. . . } public bool IsValid() { . . . } public WriteToFile() { . . . } public ReadFromFile() { . . . } } ,תכונות המחלקה Data Member שיטה בונה - Ctor שיטות המחלקה
המחלקה (Encapsulation). בנאים • הבנאים (Constructors או Ctor) הינם שיטות מיוחדות, אשר תפקידם לאתחל את ה- Data Members ברגע שנוצר אובייקט. • הפעולה הראשונה שאובייקט מבצע במהלך חייו הוא קריאה ל- Ctor . • לא ניתן ליזום קריאה לבנאי, הוא מופעל אוטומטית מייד כאשר נוצר האובייקט. • בנאי יופעל תמיד, לא ניתן להתחמק ממנו. • למחלקה תמיד יהיה Ctor , במידה ולא נוסיף אחד בעצמנו יתווסף Default Ctor אשר אינו מקבל פרמטרים ותפקידו לאפס את ה- Data Members .
המחלקה (Encapsulation). בנאים כללים ביצירת בנאים : • שם הבנאי חייב להיות זהה לשם המחלקה. • לבנאי אין ערך מוחזר, גם לא void. • בנאי יכול לקבל פרמטרים. • ניתן ולעיתים אף רצוי להעמיס בנאים. • למעט מקרים מאוד מיוחדים ונדירים, הרשאת הבנאים תמיד public.
המחלקה (Encapsulation). בנאים בנאים, דוגמה: שם הבנאי כשם המחלקה הבנאי אינו מחזיר ערך, גם לא void, מאתחל את כל התכונות. • Public class Point • { • intm_X; • intm_Y; • public Point () • { . . . } • public Point (intx, inty ) • { . . . } • . . . • }
המחלקה (Encapsulation) הפעלת ה- Ctor public class App { public static void Main() { Point p1 = new Point(); p1.Print(); Point p2 = new Point(3,7); p2.Print(); } } הפעלת בנאי ברירת מחדל (Default Ctor) הפעלת בנאי שמקבל פרמטרים.
המחלקה (Encapsulation) העברת הביצוע מבנאי אחד לבנאי אחר • ניתן הוסיף ל- Ctor רשימת אתחול (Initializer List). • באמצעות רשימת האתחול ה- Ctor יכול להיעזר ב- Ctors אחרים מהמחלקה בביצוע האתחול לאובייקט שזה אתה נוצר. • המטרה היא כמובן להימנע משכפול קוד. • ההפניה ל- Ctor באמצעות רשימת אתחול אינה מבטלת את ביצועו של ה- Ctor המקורי, אלא בנוסף אליו. ה- Ctor המקורי יבוצע אחרון.
המחלקה (Encapsulation) העברת הביצוע מבנאי אחד לבנאי אחר - המשך public class Point { … public Point () : this (0,0) {. . . } public Point (int x, int y) : this (x,y,”blue”) { this.x=x; this.y=y; } public Point (int x, int y, string c) { this.x=x; this.y=y; this.color=c; } }
המחלקה (Encapsulation) בנאים פרטיים - Private Constructors • ניתן להגדיר Ctor כבנאי פרטי (Private Constructor). • המטרה – למנוע ממחלקות אחרות להקצות אובייקט מהמחלקה. • שימושי כאשר כל המתודות הן סטאטיות (Static Method). public class Math { public static int Cos(int x) { ... } public static int Sin(int x) { ... } private Math( ) { } }
המחלקה (Encapsulation). האובייקט • אובייקט הוא מופע (Instance) של מחלקה. ממחלקה ניתן להגדיר הרבה אובייקטים. • מחלקה הנה מבנה לוגי, אובייקט הנו ישות פיזית בעל אורך חיים (Life time) וטווח הכרה (Scope) מוגדרים. • המחלקה היא "בית יוצר" לאובייקטים, ניתן לראותה גם כתבנית ממנה "יוצקים" אובייקטים בעלי מבנה זהה. • אובייקטים הינם תמיד Reference Type.
המחלקה (Encapsulation). האובייקט הקצאת אובייקט הינו תהליך בן שני שלבים: • שלב א – הקצאת דינמית של האובייקט. • שלב ב – הפעלת Constructor אשר מאתחל את האובייקט בערכים ראשוניים. לדוגמה: Point p1 = new Point(3,7); בהקצאת אובייקט תמיד יופעל Constructor , לא ניתן להימנע מכך.
המחלקה (Encapsulation). האובייקט תמונת הזיכרון לאחר הקצאת האובייקט:
המחלקה (Encapsulation). האובייקט C# מאפשרת להגדיר מספר ייחוסים המיוחסים לאובייקט יחיד: Point p1 = new Point(3,7,Color.Red); Point p2 = p1;
המחלקה (Encapsulation). האובייקט כאשר אין עוד צורך באובייקט רצוי לשחרר את הקשר בין הייחוס לאובייקט: p = null • פעולה זו אינה משחררת את האובייקט, האובייקט ישוחרר רק כאשר ה- Garbage Collection ישחררו.
המחלקה (Encapsulation). העמסת שיטות – Methods Overloading ניתן להגדיר במחלקה אחת מספר שיטות בעלות אותו השם. • C# מבחינה בין שיטות שונות בעלות אותו השם באמצעות מספר הפרמטרים או טיפוס הפרמטרים. • לא ניתן להבחין ביניהן על פי הערך המוחזר. public class ClassName { public void Method (int n1) { . . . } public void Method (int n1, int n2) {. . .} public void Method (float fn1) { . . .} }
המחלקה (Encapsulation). העמסת שיטות – Methods Overloading ניתן (ואף רצוי) להעמיס גם בנאים. לדוגמה: public class Point { … public Point () {. . . } public Point (int x, int y) {. . .} public Point (int x, int y, string c) { . . . } }
המחלקה (Encapsulation) האופרטור this • כאשר קוראים לשיטה,הקומפיילר מוסיף לרשימת הפרמטרים של השיטה פרמטר חשוב נוסף . • הפרמטר הנוסף הנו ייחוס לאובייקט שהפעיל את השיטה. • הייחוס נקרא this, הוא מתווסף אוטומטית לכל השיטות (למעט ל-static Methods). • המילה this הנה מילה שמורה. • הייחוס נשלח לשיטה בצורה מרומזת (Implicit) אולם ניתן להשתמש בו. • כאשר שם של פרמטר זהה לשם של Data Member חובה להשתמש בייחוס this על מנת שהקומפיילר ידע להבחין ביניהם. (this.x=x) • בשאר המקרים מותר להשתמש בייחוס this , אך אין זו חובה. (color=c) void Move(int x, int y)לדוגמה : { this.x = x; this.y = y; }
המחלקה (Encapsulation). חברי מחלקה קבועים ולקריאה בלבד • לעיתים ניעזר במידע שאין לשנותו, כגון: הקבוע המתמטי PI, מספר זיהוי, תאריך לידה, שם ונתיב של קובץ מידע, קובץ הגדרות האפליקציה וכו'. • C# מתירה להשתמש בחברי מחלקה קבועים ( Constants Data Members) וחברי מחלקה לקריאה בלבד (Read only Data Members). • הקבועים הם ברמת המחלקה, דהיינו , הם תמיד יהיו סטטיים (Static const). • משתני מחלקה לקריאה בלבד הם קבועים ברמת המחלקה, דהיינו, כל אובייקט יכול להכיל ערכים שונים לאותו Data Member. • ערך של משתנה Const נקבע ב- Compile Time , • ערך של משתנה Read Only נקבע ב- Run Time .
המחלקה (Encapsulation). קבועים - Const • חברי מחלקה אלו הם קבועים ברמת המחלקה, ולכן הם תמיד יוגדרו כ- Static . • C# מאפשרת להגדיר קבועים רק כ- Data Members או כקבועים לוקאליים בלבד, לא ניתן להגדיר פרמטר קבוע. • קבועים חייבים להיות מאותחלים במעמד הגדרתם, דהיינו, הקומפיילר דורש ערכים לקבועים על מנת להעבירם קומפילציה בהצלחה. • Const Data Members מגדירים באמצעות המילה השמורה const . לדוגמה: class Sample { private const float PI = 3.14f; . . . }
המחלקה (Encapsulation). קריאה בלבד – Read Only • חברי מחלקה אלו הם קבועים ברמת האובייקט. • Read only Data member ניתנים לאתחול פעם אחת בלבד, בבנאי של המחלקה, ומאותה נקודה הם אינם ניתנים עוד לשינוי. • Readonly Data Members מגדירים באמצעות במילה השמורה Readonly. class Sample { private readonly int m_ID ; . . . }
המחלקה (Encapsulation) מאפיינים Properties • תכנון נכון של מחלקה מסתיר את התכונות (Data Members) מפני כל הגורמים החיצוניים למחלקה (Data Hiding). • לעיתים צריך לשנות באובייקט את אחד מפרטי המידע? מה קורה כאשר אדם עובר דירה? כאשר עובד מקבל העלאה במשכורת? וכו' • לעיתים צריך לחשוף את ערכו של אחד מפרטי המידע. כאשר נרצה להדפיס את כתובתו של אדם, כאשר נרצה לבדוק את משכורתו של עובד וכו' • במקרים אלו ,כמו ברבים אחרים, נזדקק למכניזם מסוים אשר יאפשר לשנות בזמן ריצה (Run time) את הערכים הקיימים בתכונות.
המחלקה (Encapsulation) מאפיינים Properties • מנגנון המאפיינים (Properties) עונה הן על הצורך של השימוש בשיטות לקביעת ערך של חבר מחלקה והן על הצורך בשיטות לגישה לערכו של חבר מחלקה • המאפיין יכיל שני בלוקים: get לגישה לערכו של חבר מחלקה ו- set לשינוי ערכו של חבר מחלקה • ניתן להשתמש הן ב- Set והן ב- Get עבור התכונות או רק באחד מאותם Accessors: מאפיין שמגדיר רק בלוק get מכונה Read Only property מאפיין שמגדיר רק בלוק set מכונה Write only property • לא חובה להגדיר מאפיין עבור כל התכונות. • C# מאפשרת להגדיר גם Static Properties עבור תכונות סטאטיים ( Static Data Members).
המחלקה (Encapsulation) מאפיינים Properties value הנו משתנה אוטומטי שמוגדר בתוך set ונועד להשמת המידע החדש בשדה הרלוונטי. Value הנה מילה שמורה והטיפוס ממנו נוצר משתנה אוטומטי זה מוגדר ב – Prototype של ה – Property . private string data_member; public string PropertyName { get { return data_member; } set { data_member = value; } } החזרת ערך של תכונה השמת ערך בתכונה
המחלקה (Encapsulation) מאפיינים Properties השוואה בין מאפיינים לתכונות: • מאפיינים מכונים שדות לוגיים – Logical Fields • למאפיינים אין כתובת ואין ערך • מאחורי הקלעים מאפיינים הן שיטות לכל דבר ועניין • לא מומלץ להשתמש בשדות חישובים, לצורך כך ניתן להיעזר ב- Get Property • מבחינת המשתמש במחלקה- ה- Syntax של שימוש במאפיינים זהה ל- Syntax של שימוש במשתנים: "ללכת בלי להרגיש עם ... "
המחלקה (Encapsulation) מאפיינים Properties השוואה בין מאפיינים לשיטות: דומה • מכילים קוד • יכולים להיות virtual, abstract, override או static • מסתירים את המימוש שונה • במאפיינים אין שימוש בסוגריים • מאפיין לא יכול להיות void • למאפיין מוגדר פרמטר אחד בלבד
המחלקה (Encapsulation) מאפיינים Properties סוגים של מאפיינים: Read/write properties - מכיל הן גישת get והן גישת set. Read-only properties - מכיל גישת get בלבד, אינו קבוע. Write-only properties - מכיל גישת set בלבד. Static properties - מתייחס למחלקה ומאפשר גישה לחברי מחלקה סטטיים בלבד.
המחלקה (Encapsulation) מאפיינים Properties • תמיד נבדוק את המידע המגיע לבלוק set לפני ביצוע ההשמה בפועל על מנת לוודא שהערך תקין. • בהרבה מקרים ננצל את המאפיינים לצורך סינון המידע הזורם אל מחוץ לגבולות המחלקה מתוך בלוק get . • חשיבותם של ה- Properties היא בנוחות השימוש במחלקה, מתכנת העובד עם מחלקה בה המוגדרים בה מאפיינים מקננת התחושה שהוא עובד ישירות עם התכונות. • הקוד הרבה יותר קריא וקל לתחזוקה.
המחלקה (Encapsulation) public class Point { private int m_X; private int m_Y; public Point(int x,int y){ … } public int X { get { return this.m_X; } set { if(value >= 0 && value <=1024) this.m_X = value; } } דוגמה החזרת ערך של תכונה השמת ערך בתכונה
המחלקה (Encapsulation) יחסי הכלה בין אובייקטים קיימים שלושה סוגים של יחסי הכלה בין אובייקטים: Aggregation, Composition, Assication Composition מערכת היחסים בין אובייקט מוכל (Child) למחלקה מכילה (Parent) נקראת Compositionכאשר אורך החיים (Life Time) של האובייקטים המוכלים תלוי באורך חייו של אובייקט מהמחלקה המכילה. המחלקה המכילה מכונה גם Container. Aggregation מערכת היחסים בין Reference לאובייקט למחלקה מכילה מכונה Aggregationכאשר אורך החיים של אובייקט פנימי, הקשור לאובייקט מהמחלקה המכילה באמצעות ייחוס, אינו תלוי באורך חייו של האובייקט מהמחלקה המכילה.
המחלקה (Encapsulation) יחסי הכלה בין אובייקטים Association מערכת יחסים חלשה יותר, המגדירה שעצם אחד מכיר ונעזר בעצם השני. יחסי הכלה מזוהים על ידי "Has A": לדוגמה : למחשב PC יש מסך,מקלדת, ספק כוח, דיסק קשיח ... למכונית יש מנוע, שלדה, הגה, גלגלים.
המחלקה (Encapsulation) class Point { private int m_X; private int m_Y; public Point (){ . . . } public Point(int x,int y){ . . . } public int X { set{ . . . } get{ . . . } } public int Y { set{ . . . } get{ . . . } } public void Print(){ . . . } } יחסי הכלה בין אובייקטים דוגמה העצם המוכל מהמחלקה Point.
המחלקה (Encapsulation) יחסי הכלה בין אובייקטים דוגמה: המחלקה המכילה Circle. class Circle { private Point m_Center; private int m_Radius; public Circle() { m_Center = new Point(); m_Radius = 1; } public Circle(int x,int y,int r) { m_Center = new Point(x,y); m_Radius = r; } . . . } האובייקט המוכל הקצאת האובייקט המוכל הקצאת האובייקט המוכל
המחלקה (Encapsulation) יחסי הכלה בין אובייקטים דוגמה: המחלקה המכילה Circle - המשך. class Circle { private Point m_Center; private int m_Radius; . . . public void Print() { m_Center.Print(); Console.WriteLine("Radius = {0}",m_Radius); } } הדפסת האובייקט המוכל
המחלקה (Encapsulation) מחלקות אוסף • טיפול באובייקט יחיד שונה מטיפול באוסף אובייקטים. • טיפול באובייקט עיגול יכול להכיל: אתחול, שינוי גודל,שינוי מיקום הדפסה וכו'. • אוסף עיגולים מגדיר התנהגויות שונות לחלוטין: הוספה, הסרה, הדפסה (של כולם), מיון, חיפוש, וכו'. • מקובל להפריד בין מחלקה המטפלת ברמת האובייקט היחיד לבין המחלקה המטפלת ברבים. • מקובל שלמחלקה המטפלת ברמת היחיד (Circle לדוגמה), תיכתב מחלקה המטפלת ברמת הרבים (CircleArray לדוגמה).
המחלקה (Encapsulation) מחלקה המטפלת באובייקט יחיד מחלקות אוסף דוגמה: class Circle { private Point m_Center; private int m_Radius; . . . } מחלקה המטפלת באוסף אובייקטים class CircleArray { private Circle[] m_Arr; private int m_Counter; . . . } מערך של אובייקטים מספר האיברים הנמצאים במערך.
המחלקה (Encapsulation) מחלקות אוסף דוגמה , המשך: class CircleArray { private Circle[] m_Arr; private int m_Counter; public CircleArray() { . . . } public void Add(Circle Circle) { . . . } public void Add(int x,int y,int radius) { . . . } public void Delete(int x, int y) { . . . } public void Print() { . . . } } הטיפול במערך אובייקטים יכיל : הוספה מחיקה הדפסת כל האובייקטים, ויכול להכיל פעילויות נוספות כגון: מיון, חיפוש וכו'
המחלקה (Encapsulation). • הורשה (Inheritance). • רב צורתיות (Polymorphism). • ממשקים (Interface).
הורשה (Inheritance) • מנגנון ההורשה מגדיר יכולת של אובייקט לקבל בירושה את כל התכונות של אובייקט ממחלקה קיימת. • המחלקה היורשת מכונה מחלקה נגזרת - class Derived, המחלקה המורישה מכונה מחלקה בסיסית - class Base. • ההורשה מממשת יחסי "Is A " בין מחלקות.
הורשה (Inheritance) תחביר: יחסי הורשה בין מחלקות מסמנים על ידי האופרטור : (נקודתיים) מחלקת הבסיס class Base { } class Derived: Base { } המחלקה הנגזרת
הורשה (Inheritance) המחלקה הנגזרת Derived Class) ) מכירה את כל החלקים הציבוריים (Public) של מחלקת הבסיס שלה (Base class), אולם המרכיבים הפרטיים (Private) של מחלקת הבסיס חסומים גם בפניה. class Base { private int m_BaseNum; . . . } class Derived : Base { private int m_DerivedNum; public Derived(int bnum, int dnum) { m_BaseNum = bnum; this.m_DerivedNum = dnum; } . . . } שגיאת קומפילציה
הורשה (Inheritance) רשימת אתחול (Init List) • בהקצאת אובייקט מהמחלקה Derived נוצרים שני אובייקטים, ה- Base וה-' Derived . • ה- Base נוצר ראשון ולאחריו נוצר ה- Derived . • בהקצאת האובייקט הנגזר מופעלים שני Ctors , אחד של מחלקת הבסיס, והשני של מחלקת Derived . מכיוון שסדר הבנייה הוא מהבסיס לנגזרת ה- Ctor של המחלקה Base יופעל ראשון, ולאחריו יופעל ה- Ctor של מחלקת ה- Derived. • על מנת לייעל את תהליך בניית האובייקט המוקצה ב- Main , נדאג לשלוח פרמטרים ל- Ctor של מחלקת הבסיס באמצעות רשימת אתחול (Init List) , על מנת לבצע זאת נשתמש במילה השמורה base . • במקרה זה הקצאת האובייקט ב- Main תפעיל את ה- Ctor של המחלקה Derived , ה- Ctor של מחלקה זו יפעיל את ה- Ctor של מחלקת הבסיס אשר מקבל פרמטר בודד, ורק לאחר שהאחרון יחזור יבוצע ה- Ctor של המחלקה הנגזרת.
הורשה (Inheritance) class Base { private int m_BaseNum; public Base(int bnum) { m_BaseNum = bnum; } . . . } class Derived : Base { private int m_DerivedNum; public Derived(int bnum, int dnum):base(bnum) { this.m_DerivedNum = dnum; } . . . } Init List דוגמה: רשימת אתחול, הפעלת הבנאי המתאים של מחלקת הבסיס
הורשה (Inheritance) הורשה רב דורית – Chain Inheritance מחלקה נגזרת בעצמה יכולה לשמש, בתורה, כבסיס לגזירה על ידי מחלקה אחרת וכו' class Base { public void PrintBase(){ … } } class Derived1:Base { public void PrintDerived1() { … } } class Derived2:Derived1 { public void PrintDerived2() { … } }
הורשה (Inheritance) הורשה רב דורית – Chain Inheritance • בהקצאת האובייקט מהמחלקה Derived2 נוצר ראשון אובייקט מהמחלקה Base לאחר מכן נוצר אובייקט מהמחלקה Derived1 ולבסוף נוצר אובייקט מהמחלקה Derived2 . • המחלקה Derived2 מודעת לכך שהיא יורשת את המחלקה Derived1 , אולם אין היא מכירה את מבנהו הפנימי של Derived1, ואין היא מודעת לקיומה של המחלקה Base . • מבחינתה של Derived2 מחלקת הבסיס שלה היא "קופסא שחורה"