Top Banner
1 ההההה ההההה הההההההההההה הההההההההההה ררר ר ררר רר ררר רר ררררר
30

הורשה ופולימורפיזם

Jan 12, 2016

Download

Documents

shamus

הורשה ופולימורפיזם. צורה. ריבוע. משושה. עיגול. מוטיבציה: אפליקציית חלונות טיפוסית – נעזרת בפקדים ( Widgets ). Form. Button. Label. Textbox. פקדים הם אובייקטים לכל דבר, ומוגדרים בספריות מיוחדות שמספקות ממשקי GUI . לפקדים שראינו יש תכונות משותפות: קוארדינטות x,y על גבי הטופס. - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: הורשה   ופולימורפיזם

1

הורשה הורשה ופולימורפיזםופולימורפיזם

צורה

עיגולריבוע משושה

Page 2: הורשה   ופולימורפיזם

2

מוטיבציה:מוטיבציה:אפליקציית חלונות טיפוסית – נעזרת בפקדים

(Widgets)

Button

Textbox

Label

Form

Page 3: הורשה   ופולימורפיזם

3

פקדים הם אובייקטים לכל דבר, ומוגדרים.GUIבספריות מיוחדות שמספקות ממשקי

:לפקדים שראינו יש תכונות משותפות קוארדינטותx,y.על גבי הטופס .אורך ורוחב.טקסט

:כמו כן אפשר לחשוב על פונקציות משותפות.שינוי טקסט/גודל/מיקום.הסתרה.נעילה.ציור

Page 4: הורשה   ופולימורפיזם

4

"היינו רוצים להגדיר אובייקט שייקרא "פקדויכיל את כל התכונות המשותפות הללו.

לאחר מכן, כאשר מגדירים כל אחד מהפקדיםהספציפיים )כפתור, תיבת טקסט...( נוכל

להשתמש באובייקט ה"פקד" הכללי שלנו כדי לציין את התכונות המשותפות הללו.

המטרה: התוכנית שלנו תוכל לחשוב על"כפתור" גם כעל "פקד", בלי להתעניין

בתכונות הספציפיות של "כפתור".?בשביל מה זה טוב

Page 5: הורשה   ופולימורפיזם

5

( אובייקט טופסform מכיל רשימה של כל הפקדים )שנמצאים על הטופס.

?רשימה לכל אחד מסוגי הפקדים מה עדיף, או רשימה של *voidהאפשריים, רשימה של אובייקטים מסוג "פקד"?

נניח שצריך לצייר את כל הטופס מחדש. הטופסיצטרך לקרוא לפונקצית הציור של כל אחד מהפקדים

שנמצאים בו. מה עדיף? לבצע קריאה מיוחדת לפונקצית הציור

לכל סוג אפשרי של פקד, או לתת את אותה פקודת ציור לכולם, אבל ש"בדרך קסם" כל אחד מהם יפעל

בצורה המתאימה לו?

Page 6: הורשה   ופולימורפיזם

6

הורשה בתוכנית.is-ais-aהורשה הינה הדרך בה מביעים יחסי

:שונותנעזרים בהורשה לצורך שתי מטרות code reusecode reuse כאשר נרצה כי מספר מחלקות יהיו -

בעלות התנהגות זהה, כולן תירשנה ממחלקת אב משותפת אשר תממש התנהגות זו. בדרך זו נימנע

משכפול של הקוד.polymorphic behaviorpolymorphic behavior כאשר נרצה כי מספר -

מחלקות יחשפו ממשק זהה אך יתנהגו בצורה שונה. בשני המקרים, ההורשה תאפשר לנו להתייחס לכל

אובייקט בן כאילו היה מטיפוס אובייקט האב.

Page 7: הורשה   ופולימורפיזם

7

?is-aמה זה נניח ש"כפתור" יורש מ"פקד". במקרה זה אומרים

פקד" )באנגלית זה נשמע יותר טוב(. is-aש"כפתור בעברית: "כפתור הוא סוג מיוחד של פקד".

פירוש הדבר הוא שבכל מקום שבו ניתן להשתמשבפקד, אפשר להשתמש גם בכפתור.

,למשל, אם יש לנו פונקציה שמקבלת פקד כפרמטראפשר להעביר כפתור בתור אותו פרמטר. הפונקציה תתייחס לכפתור כאל פקד )כלומר, תתייחס לתכונות

של הכפתור שמשותפות לכל הפקדים, ולא תתעניין בתכונות הייחודיות לכפתור(.

( כל זה נכון רק להורשה ציבוריתpublic היחידה – )שנלמד בקורס הזה.

Page 8: הורשה   ופולימורפיזם

8

הורשה לשם שימוש מחדש בקוד

הידועה את הפונקציה:Stackנרצה להוסיף למחלקה ( popk)int k - אשר תוציא מהמחסניתk .איברים

.MultiStackלמחלקה המשופרת נקרא

קיימות שלוש דרכים לבצע זאת: לכתוב את MultiStack( מהתחלה cut & paste.)-להיעזר ב Stack.כשדה -לרשת מ Stack.

Page 9: הורשה   ופולימורפיזם

9

כשדה Stackשימוש באובייקט I

class MultiStack {

public:

MultiStack)int sz( : _s)sz( {}

~MultiStack)( {}

void push)int i( {_s.push)i(;}

void pop)( { _s.pop)( ; }

int top)( { return _s.top)(;}

int empty)( {return _s.empty)(;}

void popk(int k) ;private:

Stack _s;

};

עבור כל פונקציה מקורית שלStack נדרש לכתוב פונקצית

מעטפת אשר תפנה את הקריאות לאובייקט המחסנית

הפנימי. לקורא הקוד לא ברור

היא MultiStackמהתוכנית כי סוג מיוחד של מחסנית.

כיצד נראה המימוש שלpopk לא נוכל לייעל את ?

העבודה ע”י גישה ישרה למבני הנתונים של המחסנית

הוא פתרון ?(friend)האם

Page 10: הורשה   ופולימורפיזם

10

כשדה Stackשימוש באובייקט II

בעיה נוספת לשיטה זו: אם יש לנו קוד כתוב אשר נעזר במחסניות )מקבל כפרמטר מצביע או

reference לאובייקט מטיפוס Stack לא נוכל )אינו MultiStack כפרמטר כי MultiStackלשלוח לו

Stack.

int sumAndPop)Stack & s( {

int s = 0;

while )! s.empty)(( { s+=s.top)(; s.pop)( ;}

return s ;

}

Page 11: הורשה   ופולימורפיזם

11

Stackירושה מ

class MultiStack :

public Stack {public Stack {

public:

MultiStack )int sz( :

Stack(sz) {}Stack(sz) {}

~MultiStack)( {}

popk)int k( ;

};

בכדי להביע כיMultiStack הינו סוג נגדיר Stackמיוחד של

כיורש מ MultiStackאת Stack.

באופן זה כל הפונקציות מוגדרות Stackשל

באופן אוטומטי )עם אותה משמעות( עבור

. MultiStackהמחלקה

Page 12: הורשה   ופולימורפיזם

12

Stackירושה מ

ירושה כpublic היחידה אותה נלמד( גורמת( MultiStackלכך שכל משתמש של המחלקה

וגם Stackיוכל להיעזר במתודות של המחלקה .MultiStackבמתודות של

כל משתמש שלStack -יוכל להיעזר ב MultiStack-כב Stack.רגיל

Page 13: הורשה   ופולימורפיזם

13

ירושה ובונים והורסים בכל פעם שיוצרים אובייקט מהסוג היורש אנו בעצם

.Cיוצרים גם אובייקט מסוג אב. זהו המימוש ב ++

-אתחול שדות האב )ע”י הC’tor של האב, שנקרא דרך שורת האתחול של הבן( נעשה לפני יצירת שדה

של הבן.c’torכלשהו של בנו, ובפרט לפני שנקרא הריסת האב נעשית לאחר הריסת בנו ובפרט אחרי

d’tor.של הבן

שדות של האב

שדות הבן של

אובייקט אב

בן אובייקט

Page 14: הורשה   ופולימורפיזם

14

protected fields

איך נראית הפונקציהpopk האם ניתן ?

לגשת לשדות המימוש ?Stackשל המחלקה

כדי שבמחלקההיורשת ניתן יהיה

לגשת לשדות של האב יש להגדיר את השדות

.protectedכ

(ופונקציות) שדותprivate ניתנים לגישה ע”י פונקציות של

.friendsהמחלקה ו ( ופונקציות)שדותprotected

ע”י הקודמים + מחלקות יורשות

class Stack {

public : ….

protected :

int* array;

int top_index, size ;

};

Page 15: הורשה   ופולימורפיזם

15

גישה לשדות בהורשה גישה לשדות בהורשה publicpublic ( (מסוגמסוג))

StackStack Private Members Protected Members Public Members

MultiStackMultiStack Private MembersProtected Members Public Members

MultiMultiStackMultiMultiStack Private MembersProtected Members Public Members

User

Page 16: הורשה   ופולימורפיזם

17

ירושה פולימורפית בדוגמאות הקודמות האב והבן חלקו את אותה

התנהגות. התנהגות זו הייתה תקפה לשתי המחלקות ולכן שתי המחלקות חלקו:

.את אותו ממשק: אותה חתימה וערך מוחזר של הפונקציה.את אותו מימוש: אותו קוד פעל בשניהם

לעיתים צורת התנהגות זו לא טובה לנו ונרצהשלמרות שניתן יהיה לפנות לבן כמו שפונים לאב )ובפרט שישתפו את הממשק( הבן יתנהג בצורה

שונה.

Page 17: הורשה   ופולימורפיזם

18

מחלקות מעולם החי כדוגמא למחלקות בעלות התנהגות

פולימורפית. חיה

. לידה , , ת גובה משקלמזון סוגי הדפס

קול השמע

Page 18: הורשה   ופולימורפיזם

19

מחלקות בעלות התנהגות Iפולימורפית

class Animal {

public:

int getAge)( ;

virtual void makeSound)(;

private:

int weight,age ;

};

class Dog : public Animal{

void makeSound)( ;

} ;

כל בעלי החיים חולקיםדברים משותפים:

,לכולם יש משקל, גובהגיל

כולם אוכלים ומשמיעיםקולות

נרצה לתאר מחלקותמעולם החי בתוכניתנו

ולהראות קשר זה יחד עם זאת לאפשר

גמישות של התנהגות שונה כאשר הדבר נדרש

Page 19: הורשה   ופולימורפיזם

20

מחלקות בעלות התנהגות IIפולימורפית

ניתן במחלקה היורשת ממחלקה אחרתלהגדיר מחדש פונקציות אשר הוגדרו

במחלקת האב. אולם הדבר יגרום לכך שהפונקציה שתיקרא

תלויה בדרך בא קראנו לה:Dog * d = new Dog)(;Animal * a = d ; a->makeSound)(; d->makeSound)( ;

אם נרצה שההתנהגות השונה תחול גםכאשר ניגשים לפונקציה דרך מצביע לאב -

נעזר בפונקציות ווירטואליות.

Page 20: הורשה   ופולימורפיזם

21

מחלקות בעלות התנהגות IIIפולימורפית

כאשר מגדירים פונקציה וירטואלית בעצם אומרים שהאופןהמדויק בו יתנהג האובייקט תלוי בטיפוס הבן עימו אנו

עובדים. למי שנעזר באובייקט האב לא משנה מה הטיפוס המדויק של הבן והוא יכול לעבוד עם כולם באופן אחיד.

class Cat : public Animal{

public:

void makeSound)( {

cout << “miao\n”;

}

} ;

class Dog : public Animal{

public:

void makeSound)( {

cout << “vuf vuf\n”;

}

} ;

Page 21: הורשה   ופולימורפיזם

22

מחלקות בעלות התנהגות פולימורפית IV

main )( {

Animal* dog = new Dog)(;

Animal* cat = new Cat)(;

Animal* whoami = new Bear)(;

dog->makeSound)(;

cat->makeSound)(;

whoami->makeSound)(;

}

פלט התוכנית

vuf vuf

miao

orrrr

Page 22: הורשה   ופולימורפיזם

23

שיטה חליפית להתנהגות פולימורפית

בC מקובל להיעזר בשדות type לכל חיה . היינו שומרים קוד משלה, ובכל פונקציה היינו

ענק שהיה אומר מה switchנעזרים במשפט לעשות לכל טיפוס.

הבעיות בגישה זו הינן שבכל פעם שנרצהלהוסיף חיה למערכת נדרשת לשנות קוד

בהרבה פונקציות - מאוד רגיש ובעייתי.

Page 23: הורשה   ופולימורפיזם

24

Abstract Classes קיימות מחלקות המייצגות רעיון מופשט ויש

להן משמעות רק כבסיס למחלקות אחרות

מחלקה עם מתודהPure Virtual אחת או( מחקלה אבסטרקטיתיותר( היא

לא ניתן ליצור אובייקטים של מחלקה שכזו

class Shape {public:

Shape)int x, int y( : center_x)x(,center_y)y({}virtual double area)( const = 0;

protected:int center_x, center_y ;

};

Page 24: הורשה   ופולימורפיזם

25

class Shape {public:

Shape)int x, int y( : center_x)x(,center_y)y({}virtual double area)( const = 0;

protected:int center_x, center_y ;

};

class Circle: public Shape {public:

Circle)int x, int y, int r(: Shape)x,y(, radius)r({} double area)( const {

return )PI*radius*radius(;}

private: int radius;

} ;

class Rect: public Shape {public:

Rect)int x, int y, int h, int w(:

Shape)x,y(,height)h(,width)w( {}double area)( const

{return )height*width(;}private:

int height, width;} ;

דוגמא מסכמת: צורותדוגמא מסכמת: צורות

Page 25: הורשה   ופולימורפיזם

26

int main)( {…Shape* p[N];

// an array of rectangles & circles // initialization…double total_area=0; for )int j = 0; j < N; ++ j total_area += p[j] -> area) (;

}

דוגמא מסכמת: צורותדוגמא מסכמת: צורות

Page 26: הורשה   ופולימורפיזם

27

Exceptions

הסטייל החדש לטיפול בשגיאות

main)(

return BAD_ARG

catch

throw

BAD_ARG

func)(

Page 27: הורשה   ופולימורפיזם

28

C Styleint DoSomething)( {

long *a, c; FILE *b; a = malloc)sizeof)long( * 10(; if )a == NULL(

return ERR_MEM; b = fopen)"something.bah", "rb"(; if )b == NULL( {

free)a(; return ERR_FILE;

} fread)a, sizeof)long(, 10, b(; if )a[0] != 0x10( {

free)a(; fclose)b(; return ERR_INPUT;

} fclose)b(; c = a[1]; free)a(; return SUCEES;

}

Page 28: הורשה   ופולימורפיזם

29

Try-catch-throw

try - הגדרת בלוקExceptionsCatch תפיסת – ExceptionThrow זריקת – Exception

Page 29: הורשה   ופולימורפיזם

30

<include <iostream.h#?מה פלט התוכניתvoid func)({ throw "ERROR";

cout << "Does this code happened?" << endl;

return;}

int main)( {try{ func)(;}catch )char* string({ cout << string << endl;}cout << "END OF PROGRAM" << endl;return 0;

}

Page 30: הורשה   ופולימורפיזם

31

Exceptions

// bad_alloc standard exception #include <iostream> #include <exception>

using namespace std;

int main )( { try {

int* myarray= new int[1000]; } catch )exception& e( {

cout << "Standard exception: " << e.what)( << endl; } return 0;

}