מלבן צבעוני נרצה לבנות מחלקה המייצגת מלבן צ בע וני שצל עותיו מקבי לות לצירים ונעמוד על היתרונות גרסאות למחלקה, נציג 3 והחסרונות של כל גרסה נתמקד בגרסה השלישית (המשתמשת לבסוף, ונחקור דרכה את (Java במנגנון הירושה של מנגנון הירושה Java תכנ ות מתקדם בשפת ירושה אוהד ברזילי אוניברסיטת תל אביב /** returns the rectangle's color */ public Color color() { return col; /** returns a point representing the bottom-right corner of the rectangle*/ public IPoint bottomright() { return factory.createpoint(topright.x(), (), bottomleft.y()); /** returns a point representing the top-left corner of the rectangle*/ public IPoint topleft() { return factory.createpoint(bottomleft.x(), (), topright.y()); /** returns a point representing the top-right corner of the rectangle*/ public IPoint topright() { return factory.createpoint(topright.x(), (), topright.y()); /** returns a point representing the bottom-left left corner of the rectangle*/ public IPoint bottomleft() { return factory.createpoint(bottomleft.x(), (), bottomleft.y()); package il.ac.tau.cs.advjava.shapes; public class ColoredRectangle1 { private Color col; private IPoint topright; private IPoint bottomleft; private PointFactory factory; /** constructor using points */ public ColoredRectangle1 (IPoint( bottomleft, IPoint topright, PointFactory factory, Color col) ) { this.bottomleft = bottomleft; this.topright = topright; this.factory = factory; this.col = col; /** constructor using coordinates */ public ColoredRectangle1 (double x1, double y1, double x2, double y2, PointFactory factory, Color col) ) { this.factory = factory; topright = factory.createpoint(x1,y1); bottomleft = factory.createpoint(x2,y2); this.col = col; /** move the current rectangle by dx and dy */ public void translate(double dx, double dy){ topright.translate(dx, dy); bottomleft.translate(dx, dy); /** rotate the current rectangle by angle degrees with respect to (0,0) */ public void rotate(double angle){ topright.rotate(angle); bottomleft.rotate(angle); /** change the rectangle's color */ public void setcolor(color c) { col = c; /** returns the horizontal length of the current rectangle */ public double width(){ return topright.x() - bottomleft.x(); /** returns the vertical length of the current rectangle */ public double height(){ return topright.y() - bottomleft.y(); /** returns the length of the diagonal of the current rectangle */ public double diagonal(){ return topright.distance(bottomleft);
Just Do It ארגונים אשר אינם משתמש ים בקוד רק כי הוא נאלצים לחרוג מתחומי העיסוק נכתב אצלנו" "לא שלהם לצורכי כתיבת תשתיות וההפשטה ההכמסה הדבר סותר את רעיון שביסו דו של ה תכנות מונחה העצמ ים ומפחית את השימו ש החוזר בקוד /** returns a string representation of the rectangle */ public String tostring(){ return "bottomright=" + bottomright() + "\tbottomleft=" + bottomleft + "\ttopleft=" + topleft() + "\ttopright=" + topright ; "\tcolor is: " + col ; הקוד לעיל דומה מאוד לקוד שכבר ראינו זהו שכפול קוד נוראי הספק צריך לתחזק קוד זה פעמיים כאשר מתגלה באג (למשל rotate לא שומר על הפרופורציה של המלבן המקורי), יש לדאוג לתקנו בשני מקומות הדבר נכון בכל סדר גודל: פונקציה, מחלקה, ספרייה, תוכנה, מערכת הפעלה וכו') package il.ac.tau.cs.advjava.shapes; public class ColoredRectangle2 { private Color col; private Rectangle rect; /** constructor using points */ public ColoredRectangle2 (IPoint( bottomleft, IPoint topright, PointFactory factory, Color col) ) { this.rect = new Rectangle(topRight, bottomleft,, factory); this.col = col; /** constructor using coordinates */ public ColoredRectangle2 (double x1, double y1, double x2, double y2, PointFactory factory, Color col) ) { this.rect = new Rectangle(x1, y1, x2, y2, factory); this.col = col; Just Do It אחורה" כלפי לקוחותיו לל"תאימות מחוייב ספק תוכנה כלומר קוד שסופק (backward compatibility) גם לאחר שיצאה גרסה חדשה ימשיך להיתמך (לעבוד) של אותו הקוד בשדרוגי התוכנה עיקביים הדבר מחייב ספקים להיות כדי להיות מסוגלים לתמוך במקביל בכמה גרסאות אחת הדרכים לעשות זאת היא עע"י שימוש חוזר בקוד באמצעות הכלה של מחלקות קיימות /** returns the horizontal length of the current rectangle */ public double width(){ return rect.width(); /** returns the vertical length of the current rectangle */ public double height(){ return rect.height(); /** returns the length of the diagonal of the current rectangle */ public double diagonal(){ return rect.diagonal(); /** returns the rectangle's color */ public Color color() { return col; /** returns a point representing the bottom-right corner of the rectangle*/ public IPoint bottomright() { return rect.bottomright(); /** returns a point representing the top-left corner of the rectangle*/ public IPoint topleft() { return rect.topleft() ; /** returns a point representing the top-right corner of the rectangle*/ public IPoint topright() { return rect.topright() ; /** returns a point representing the bottom-left corner of the rectangle*/ public IPoint bottomleft() { return rect.bottomleft();
/** returns a string representation of the rectangle */ public String tostring(){ return rect + "\tcolor is: " + col ; Rectangle כשדה שלה מכילה ColoredRectangle2 המחלקה המחלקה החדשה תומכת בכל שרותי המחלקה המקורית פעולות שניתן היה לבצע על המלבן המקורי מופנות לשדה rect delegation) - האצלה) הערה: בסביבות פיתוח מודרניות ניתן לחולל קוד זה בצורה אוטומטית! נשים לב כי המתודה tostring מוסיפה התנהגות למתודה tostring של המלבן המקורי (הוספת הצבע) הבנאים של המחלקה החדשה קוראים לבנאים של המחלקה Rectangle /** move the current rectangle by dx and dy */ public void translate(double dx, double dy){ rect.translate(); /** rotate the current rectangle by angle degrees with respect to (0,0) */ public void rotate(double angle){ rect.rotate(); /** change the rectangle's color */ public void setcolor(color c) { col = c; שימוש חוזר ותחזוקה יחסים בין מחלקות שיתופיות) קשירות, Association (הכרות, דו כיוונית: כעת קל יותר לתחזק במקביל את שני המלבנים יתבטא אוטומטית Rectangle כל שינוי במחלקה וכך ישדרג הן את קוד לקוחות ColoredRectangle2 במחלקה ColoredRectangle2 והן את קוד לקוחות Rectangle בין שתי המחלקות מובנית העיקביות ואולם נרצה,Rectangle הוא לקוח של ColoredRectangle2 לבטא יחס נוסף הקיים בין המחלקות ניזכר ביחסי המחלקות שבהם נתקלנו עד כה חד כיוונית: רפלקסיבית: יחסים בין מחלקות יחסים בין מחלקות Composition (הרכבה) שבו הרכיב תלוי Aggregation מקרה פרטי של קיום למשל) במיכל (משך Composition ע"י עצמים מקובל לציין ++C בשפת מוצבעים Aggregation ע"י עצמים מוכלים וו- Aggregation (מכלול) המבטא הכלה Association סוג של החלקים עשויים להתקיים גם ללא המיכל המיכל מכיר את רכיביו אבל לא להיפך
דיון יחסים בין מחלקות - היחסים לעיל? לל- 3 איך נמפה יחסי ספקספק-לקוח is-a יחס אנו אומרים שחל עליה כאשר מחלקה היא סוג של מחלקה אחרת, is-a היחס class A is-a class B B Generalization יחס זה נקרא גם יחס זה אינו סימטרי מלבן צבעוני הוא סוג של מלבן אבל לא להיפך סוג-מיוחד-של,,ל תתת ניתן לראות במחלקה החדשה מקרה פרטי, קבוצה של המחלקה המקורית המאפיינות בדרך כלל יהיו למחלקה החדשה תכונות ייחודיות, שבוטאו בה שלא באו לידי ביטוי במחלקה המקורית (או אותה, בכלליות) aggregation vs. מה היחס בין מלבן ונקודותיו ) (composition מה ההבדל ביחס שבין מלב ן ונקודותיו ליחס שבי ן מלבן צב עו ני ומלבן מנגנון הירושה (הורשה?) Is-a a Example בין is-a מספקת תחביר מיוחד לבטא יחס Java הכלת המחלקה המקורית כשדה מחלקות (במקום במחלקה החדשה) המנגנון מאפשר שימוש חוזר ויכולת הרחבה של מחלקות קיימות extends מחלקה אשר תכריז על עצמה שהיא את כל תכונות תקבל במתנה (בירושה) מחלקה אחרת, כאילו שהן תכונותיה שלה אותה מחלקה (כמעט) מרחיבה מחלקה אחת בדיוק (ואולי Java כל מחלקה ב או יותר)) מממשת מנשקים (0 AlarmClock setalarm() setalarmstate() Clock settime() getseconds() getminutes() gethours() secondelapsed()... AnalogClock getsecondspointerangle() getminutespointerangle() gethourspointerangle() Rectangle ירושה מ מונחי ירושה Rectangle public Rectangle(IPoint bottomleft, IPoint topright ) public double width() public double diagonal() public void translate(double dx, double dy) public void rotate(double angle) public IPoint bottomright()... קשר ירושה ב- JAVA הרחבה (extension) ColoredRectangle public ColoredRectangle (IPoint bottomleft, ) public Color color() public void setcolor(color col)... הורה מחלקת בסיס (base) מחלקת על class) (super צאצא מחלקה נגזרת (derived) תת מחלקה (subclass) package il.ac.tau.cs.advjava.shapes; public class ColoredRectangle3 extends Rectangle { private Color col; // Rectangle יורשת מהמחלקה ColoredRectangle3 המחלקה והשרותים של Rectangle היא מגדירה שדה נוסף נוסף על השדות col - בנאים ומתודות סטטיות אינם נורשים
בנאים במחלקות יורשות בנאים במחלקות יורשות /** constructor using points */ public ColoredRectangle3(IPoint bottomleft, IPoint topright, PointFactory factory, Color col) ) { super(topright (topright, bottomleft,, factory); this.col = col; /** constructor using coordinates */ public ColoredRectangle3(double double x1, double y1, double x2, double y2, PointFactory factory, Color col) ) { super(x1, y1, x2, y2, factory); this.col = col; הקדמון ביותר ומטה) מחלקות נבנות מלמעלה למטה (מההורה בכל בנאי כוללת קריאה לבנאי מחלקת הבסיס השורה הראשונה super(constructorargs בתחביר: constructorargs) מדוע? אם לא נכתוב בעצמנו את הקריאה לבנאי מחלקת הבסיס יוסיף super() הקומפיילר בעצמו את השורה אם למחלקת הבסיס אין בנאי ריק זוהי שגיאת קומפילציה במקרה זה, שרותים הוספת שרותים (overriding) דריסת מחלקה יכולה לדרוס מתודה שהיא קיבלה בירושה שיקולי יעילות אחריות" הוספת "תחומי על המחלקה היורשת להגדיר מתודה בשם זהה זוהי למתודה שהתקבלה בירושה (אחרת ובחתימה זהה העמסה ולא דריסה) ניתן להשתמש כדי להשתמש במתודה שנדרסה, super.methodname(arguments בתחביר: arguments) נוספים שרותים המחלקה היורשת יכולה להוסיף שלא הופיעו במחלקת הבסיס: (מתודות) /** returns the rectangle's color */ public Color color() { return col; /** change the rectangle's color */ public void setcolor(color c) { col = c; שרותים (overriding) דריסת שרותים (overriding) דריסת tostring רוצה לדרוס את ColoredRectangle3 המחלקה כדי להוסיף לה גם את הדפסת צבע המלבן כדי למנוע שכפול קוד היא משרשרת את תוצאת ללוגיקה החדשה המקורית (שנדרסה) tostring מה יעשה הקוד הבא? @Override public String tostring() { return tostring() + "\tcolor is " + col; אופציונלי @Override public String tostring() { return super.tostring.tostring() + "\tcolor is " + col;
שימוש במלבן עניין של ספקים ירושה הוא מנגנון אשר בא לשרת את הספק כל עוד המחלקה מממשת מנשק שהוגדר מראש, לאא עם מי הוא עובד גם לא יודע) איכפת ללקוח (והוא ברמה התחבירית ניתן לראות ירושה כסוכר תחבירי להכלה להיות ColoredRectangle2 שב- rect אם נחליף את שם השדה ColoredRectangle3 נקבל התנהגות דומה לזו של super ואולם מנגנון הירושה פרט לחסכון התחבירי כולל גם התנהגות שנדגים מיד) פולימורפית (כפי package il.ac.tau.cs.advjava.shapes; public class Client { public static void main(string[] args) ) { IPoint tr = new PolarPoint(3.0, (1.0/4.0)*Math.PI Math.PI); // theta now is 45 degrees IPoint bl = new CartesianPoint(1.0, 1.0); PointFactory factory = new PointFactory(true true); ColoredRectangle3 rect = new ColoredRectangle3(bl, tr,, factory, Color.BLUE); rect.translate(10, 20); rect.setcolor(color.green); Inherited from Rectangle System.out.println(rect); Added in ColoredRectangle3 tostring was overridden in ColoredRectangle3 עקרון ההחלפה פולימורפיזם וירושה package il.ac.tau.cs.advjava.shapes; public class Client { public static void main(string[] args) ) { IPoint tr = new PolarPoint(3.0, (1.0/4.0)*Math.PI Math.PI); // theta now is 45 degrees IPoint bl = new CartesianPoint(1.0, 1.0); PointFactory factory = new PointFactory(true true); Rectangle rect = new ColoredRectangle3(bl, tr,, factory, Color.BLUE); rect.translate(10, 20); rect.setcolor(color.green); // Comiplation Error System.out.println(rect); שבכל הקשר שבו משתמשים עקרון ההחלפה פירושו, במחלקה במחלקה המקורית ניתן להשתמש (לוגית) החדשה במקומה נשתמש במנגנון הירושה רק כאשר המחלקה החדשה עקרון עם מחלקה קיימת וכן נשמר is-a מקיימת יחס ההחלפה אלו מובילה לבעיות תחזוקה שני עקרונות אי שמירה על במערכות גדולות ודינמי טיפוס סטטי ודינמי טיפוס סטטי הקומפיילר הוא ס טטי: קונסרבטיב י שמרן, הפעלת שרות על הפנייה מחייב את הגדרת השרות בטיפוס ההפנייה הסטטי של מנגנון זמן הריצה הוא דינא מי: dynamic dispatch ו ירטואלי, פולימורפי, המוצבע השרות שיופעל בזמן ריצה הוא השרות שהוגדר בעצם ההפנייה) הדינאמי של בפועל (הטיפוס Rectangle r = new ColoredRectangle3( ); שלפ י ו נוצר העצם. טיפ וס הבנאי טיפוס של עצם: טיפוס זה קבוע ו אינו משתנה לאו רך חיי העצם. מים מבחינים בי ןן: ( references )לעצ לגבי הפניות הטיפוס שהוגדר בהכרזה על ההפניה טיפוס סטטי: המוצבע טיפוס העצם הטיפוס הדינאמי: הטיפוס הדינאמי חייב להיות נגזרת של הטיפוס הסטטי Rectangle r = new ColoredRectangle3( ); טיפ וס העצם הט יפ וס הד י נמ י של ההפנ י ה הט יפ וס הסטט י של ההפנ י ה טיפ וס העצם הט יפ וס הד י נמ י של ההפנ י ה הט יפ וס הסטט י של ההפנ י ה
של הפניות ודינמי טיפוס סטטי טיפוס סטטי טיפוס סטט י של מחלקה צריך להיות הכללי ביותר האפשרי בהקשר שבו הוא מופיע אם קיים עדיף מנשק, מחלקה המרחיבה מחלקה אחרת מממשת אוטומ טית את כל המנשקים שמומ שו ב מחלקת הבסיס void expectrectangle(rectangle r); void expectcoloredrectangle(coloredrectangle3 cr); void bar() { Rectangle r = new Rectangle(...); ColoredRectangle3 cr = new ColoredRectangle3(...); r = cr; expectcoloredrectangle(cr); expectrectangle(cr); expectrectangle(r); expectcoloredrectangle(r); The static type of r remains Rectangle. Its dynamic type is now ColoredRectangle3 Compilation Error despite that the dynamic type of r is ColoredRectangle3 וירושה ניראות וירושה ניראות מעוניינת לממש מחדש את המתודה ColoredRectangle3 מה אם המחלקה להשתמש במימוש הקודם כקופסא שחורה) tostring (ולא Rectangle (ואף יורשת מהמחלקה ColoredRectangle3 על אף שהמחלקה Rectangle אין לה הרשאת גישה לשדותיה הפרטיים של מכילה אותה!) קירוב ראשון: כדי לגשת למידע זה עליה לפנות דרך המתודות הציבוריות: /** returns a string representation of the rectangle */ public String tostring(){ return "bottomright is " + bottomright() + "\tbottomleft is " + bottomleft() + "\ttopleft is " + topleft() + "\ttopright is " + topright() ; "\tcolor is: " + col ; /** returns a string representation of the rectangle */ public String tostring(){ return "bottomright is " + bottomright() + "\tbottomleft is " + bottomleft + "\ttopleft is " + topleft() + "\ttopright is " + topright ; "\tcolor is: " + col ; השדות הוגדרו ב Rectangle כ private ועל כן הגישה אליהם אסורה package il.ac.tau.cs.advjava.shapes; public class Rectangle { וירושה ניראות קיימים כמה חסרונות בגישה של מחלקה יורשת לתכונותיה הפרטיות של מחלקת הבסיס בעזרת מתודות ציבוריות: יעילות סרבול קוד protected חדשה ניראות לשם כך הוגדרה דרגת וירושה ניראות protected IPoint topright; protected IPoint bottomleft; private PointFactory factory; // package il.ac.tau.cs.advjava.otherpackage; public class ColoredRectangle3 extends Rectangle { /** returns a string representation of the rectangle */ public String tostring(){ return "bottomright is " + bottomright() + "\tbottomleft is " + bottomleft + "\ttopleft is " + topleft() + "\ttopright is " + topright ; "\tcolor is: " + col ; מאפשרים גישה מתוך: protected שדות שהוגדרו כ מחלקות באותה החבילה מחלקות נגזרת, המחלקה המגדירה, אינה כוללת מחלקות באותה protected בשפות מונחות עצמים אחרות החבילה
private vs. protected וירושה ניראות private נ ירא ו ת יש מתכנת ים ש טו ענ ים כ י Java היתה ב וכ י לו OO סותרת א ת רו ח ה (package אמית ית (ללא protected נירא ות תמ יד private היה להשתמש בה במק ום אחרים ט וענ ים ההיפך שתי הגיש ות מ קובל ות ולשת י הן נ י מו קים ט וב ים ותלו יה פרגמט ית הבחירה בי ן ש תי הגיש ות היא בסי טואצ יה Modifier: Private Package (default) Protected Public Accessed by class where member is define Accessed by Package Members No Accessed by Sub-classes No No (unless subclass happens to be in same package) (even if subclass & super-class are in different packages) Accessed by all other classes No No No private vs. protected private vs. protected protected בעד, coloredrectangle is a Rectangle ולכן לא הגיוני שלא הוא עומד בב"מ ב חן ההחלפה" יהיו לו אותן הזכויות. coloredrectangle has a Rectangle ול כן יש צורך לאפשר לו גישה בתו כו) (מכיל למימ ושו הפנימ י טה יעילה ופשו :private בעד כשם שאנו מסתירים מלקוחותינו את המימוש כדי להגן על שלמות המידע עלינו ל הסתיר זאת גם מצא צאנו איננו מכירים את יורשנו כפי ש איננו מכירים את לקוחותינו עלול להפר את חוזה מחלקת צאצא עם עוד ף כחח להעביר את עצמו ללק וח המצפה לקבל הבסיס, את אביו ולשבו ר את התוכנה מתודה שהוגדרה כ במחלקות נגזרת ממחלקה שהוגדרה כ מניעת ירושה לא ניתן יהיה לדרוס final לא ניתן יהיה לרשת final מדוע?.final היא String המחלקה דוגמא: Object כולם יורשים מ יורשת Java אמרנו קודם כי כל מחלקה ב ומה אם הגדרת המחלקה ממחלקה אחת בדיוק.? extends לא כוללת פסוקית במקרה זה מוסיף הקומפיילר ב מקומנו את extends Object הפסוקית public class Rectangle {{ public class Rectangle extends java.lang.object {{ public final finalclass String {{ public class MyString extends String{ שגיאת קומפילציה
Object כולם יורשים מ Object כולם יורשים מ מהווה בסיס לכל המחלקות ב Object המחלקה ומכילה מספר טרנזיטיבית) בצו רה Java (אולי בסיסיי ם שכל מחלקה צריכה (?) שרותים חלק מהמתודות קשורות לתכנות מרובה חוטים וילמדו (multithreaded programming) בהמשך הקורס שיבוט והשוואה שיבוט עצמים x = y.clone () הינה פעולה אשר יוצרת עותק זהה לזה של העצם - clone ומחזירה מצביע אליו המשובט לא מובטח כי מימוש ברירת המחדל יעבוד אם העצם המבוקש אינו implements Cloneable מבטאת השוואה בין שני עצמים שדה-שדה. בדר"ככ equals :Object ע"י האופרטור '== ==' (השוואת מימוש ברירת המחדל של הפניות), deep_equals בהקשר הזה ניתן לדבר על deep_clone ו- שיבוט רדוד ושיבוט עמוק שיבוט רדוד ושיבוט עמוק b איך תשפיע הפעולה: c = a.clone() איך תשפיע הפעולה: b = a
שיבוט רדוד ושיבוט עמוק איך תשפיע הפעולה: d = a.deep_clone() deep_clone() אינה מתודה סטנדרטית של.Object בחלק מן המקרים נממש את clone במובן עמוק (ריקורסיבי) ולפעמים במובן רדוד Collection Interfaces מנשקים ויחס ירושה Collection Unordered Rejects duplicates Set List Ordered Allows duplicates Queue FIFO Order Allows duplicates Unordered Rejects duplicates Map SortedMap Ordered Rejects duplicates כשם ש שתי מח לקות מקיימות י חס ירושה כך גם מנשקים יכולים לקיים את אותו היחס 2 מחלקה המממשת מנשק מחוי בת לממש את כל המתודות של אותו מנשק וכל המתודות שהוגד רו בהוריו סוגי מחסניות IStack לדוגמא: SortedSet Ordered Rejects duplicates IBoundedStack IUnBoundedStack ISumStack היררכיות ירושה אמא יש רק אחת כי לכל מחלקה יש מחלקת בסיס אחת נדגיש, ועל כ ן גרף הירושה הוא בעצם עץ בדיוק, (Object ורשו המחלקה (שש מימ וש מנשקים אינו חלק ממנגנון הירושה זאת על אף שבין מנשקים לבין עצמם י ש יחסי ירושה צורות גיאומטריות במ יש ו ר דוגמא לעץ ירושה: מחלקות רבות במערכות מונחות עצמים הן חלק ממ"עצי ירושה" ירושה" אוו "היררכיות שורש העץ מבטא קונספט כללי וככל שיורדים במורד עץ הירושה המחלקות מייצגות רעיונות צרים יותר שמחלקה יורשת לאמר בחרו Java למרות שבשפת הרי שבמובן מסוים היא מחלקת בסיס, מרחיבה מצמצמת את קבוצת העצמים שהיא מתארת
abstract classes היררכית מחלקות ומנשקים ולאליפסה יש צבע למצולע (polygon) Shape יגרום לשכפול בשקף הקודם, שמצוייר עץ הירושה כפי והמתודות ישוכפלו ויתוחזקו פעמיים) color קוד (השדה לא ניתן להוסיף למנשק שדות או מימושי מתודות מחד, אם ניצור לשתי המחלקות אב משותף מה יהיו מימושיו מאידך, חישוב ההיקף עבור מצולע כלשהו ועבור עבור היקף (דרך אליפסה כלשהי שונה בתכלית) Ellipse Circle Trapezoid Polygon Parallelogram Triangle לשם כך קיימת המחלקה המופשטת מחלקה עם מימוש חלקי (abstract class) Diamond Rectangle היררכית מחלקות ומנשקים Shape <<abstract>> AbstractShape abstract classes מחלקה מופשטת דומה למחלקה רגילה עם הסייגים הבאים: בירושה ממחלקת בסיס או מנשקים שהיגיעו ניתן לא לממש מתודות ניתן להכריז על מתודות חדשות ולא לממשן לא ניתן ליצור מופעים של מחלקה מופשטת Ellipse Polygon במחלקה מופשטת ניתן לממש מתודות ולהגדיר שדות Circle Trapezoid Parallelogram Triangle מחלקות מופשטות משמשות כבסיס משותף למחלקות יורשות לצורך חיסכון בשכפול קוד Diamond Rectangle AbstractShape נגדיר את המחלקה AbstractShape המחלקה המופשטת המחלקה מממשת רק חלק מן המתודות של המנשק כדי לחסוך שכפול קוד ב"מורד ההיררכיה" את המתודות הלא ממומשות היא מציינת ב abstract public abstract class AbstractShape implements Shape { protected Color color ; public Color getcolor() { return color ; public void setcolor(color c) { color = c ; public abstract void display(); public abstract double perimeter(); public abstract void rotate(ipoint center, double angle); public abstract void translate(ipoint p); Shape המנשק public interface Shape { public double perimeter(); public void display(); public void rotate(ipoint center, double angle); public void translate(ipoint p); public Color getcolor(); public void setcolor(color c); //...
Polygon המחלקה AbstractShape המחלקה המופשטת public class Polygon extends AbstractShape { public double perimeter() {... public void display() {... public void rotate(ipoint center, double angle) {... public void translate(ipoint p) {... public int count() { return vertices.size(); private List<IPoint> vertices; public abstract class AbstractShape implements Shape { protected Color color ; public Color getcolor() { אפשר לוותר על ההצהרה return color ; public void setcolor(color c) { color = c ; מחלקות מופשטות ומנשקים האפשרות להגדיר מחלקות מופשטות ללא מטש טשת (abstract מתודות מימ וש כלל (רק את ההבחנה בין מנשק ובין מחלקה מופשטת ואולם יש לזכור: חיסכון אצל הלקוח מנשק: חיסכון אצל הספק בכלל): מחלקה מופשטת (וירושה