בתרגול הקודם
description
Transcript of בתרגול הקודם
בתרגול הקודםהורשה:•
ניתן להרחיב רק מחלקה אחת– – עובר בהורשהprivateכל מה שלא –superהמילה השמורה –יצירת היררכיה––Objectהיא שורש ההיררכיה דריסה–
instanceofאופרטור •Objectהמחלקה •
toString, equalsהשיטות –
פולימורפיזם•חד כיווניות– 1
11תרגול המשך תכנות מונחה עצמים
2
היום בתרגול
כללי הרשאות בהורשה•מחלקות אבסטרקטיות•
3
( בהורשהvisibility modifiersכללי הרשאות )
public -שדות ושיטות המוגדרים כ –public ניתנים לגישה מתוך ומחוץ למחלקה.
protected -שדות ושיטות המוגדרים כ –protected ניתנים לגישה מתוך המחלקה וממחלקות היורשות מהמחלקה, אך
אינם ניתן לגישה ממחלקות אחרות *. באותו public מתנהג כמו protected אחר. package)* ממחלקות אחרות הנמצאות ב
package)
private-שדות ושיטות המוגדרים כ – private אינם ניתנים לגישה מחוץ למחלקה. ניסיון לגשת לשדה או שיטה כזו מחוץ למחלקה
.שגיאת קומפילציהיעורר
4
שיטות לא יכולות להידרס ע"י שיטה מרמת שיתוף נמוכה יותר, זו שגיאת •קומפילציה. כלומר:
private או protected עם publicלא ניתן לדרוס שיטה –private עם שיטה protectedלא ניתן לדרוס שיטה –
public class Book { public String getName() {
… }}
public class Dictionary extends Book { protected String getName() {
… } }
Compilation Error
: מה ההיגיון מאחורי שגיאה זו?שאלהבלעדיה הייתה מתקבלת סתירה
לעקרון הפולימורפיזם5
Book b = new Dictionary)(;System.out.println )b.getName)( (;
( בהורשהvisibility modifiersכללי הרשאות )
משתנים אינם עוברים דריסה בהורשה.• עוברות בהורשה.privateשיטות שאינן •
שיטות פרטיות נועדו למימוש פנימי של מחלקת האב, ואינן ניתנות –לשימוש ע"י תת מחלקה.
תת-המחלקה לא מכירה את המשתנים והשיטות הפרטיים של המחלקת –האב, ממנה היא יורשת, ולכן עשויה גם להכריז על משתנים ושיטות
פרטיים בעלי אותו שם וחתימה.
:דוגמה•עסק היא סוג של חנות–
עסק: דמי שכירות, עובדים, הוצאות חודשיות•חנות: פריטי סחורה, הוצאות חודשיות הכוללות אחזקת מלאי.•
כל מחלקה מומשה ע"י מתכנתת אחרת–)(calcSumבכל מחלקה מימוש שונה לשיטה פרטית - –
6
( בהורשהvisibility modifiersכללי הרשאות )
public class Business {
protected Employee[] employees;protected double monthlyRent;
......
// calculates total monthly expenses
public double monthlyExpenses() {double salaries = calcSum();return this.monthlyRent + salaries;
}
// calculates monthly salaries
private double calcSum() { double sum = 0;for (int i=0; i<this.employees.length; i=i+1) {
sum = sum + this.employees[i].getSalary();}return sum;
}......}
7
קריאה לשיטה פרטית
public class Shop extends Business {protected Item[] items;
......
// override: calculates total monthly expenses
public double monthlyExpenses() {double itemPrices = calcSum();return itemPrices + super.monthlyExpenses();
}// No override: calculates total item prices
private double calcSum() {double sum=0;for (int i=0; i<this.items.length; i=i+1) {
sum = sum + this.items[i].getPrice();}return sum;
}......}
8
, protected ל-calcSum: אם נשנה את המאפיין של שאלה?monthlyExpensesמה תחשב
קריאה לשיטה פרטית
סיכום חוקי גישה לשיטות ושדות בהורשה :Javaב-
( קובע בזמן הידור אילו reference typeטיפוס המשתנה )טיפוס המצביע/ 1.שיטות ניתן להפעיל על המשתנה ולאילו שדות של המשתנה ניתן לגשת.
המופיעה במחלקת-אב ובתת-מחלקה, בקריאה לשיטה שאינה פרטית2.אם ע"י קריאה ישירה או ע"י שימוש באופרטור השייכות ).(, הקוד המופעל
שעליו ) )instance typeבהתאם למחלקת האובייקט בפועלנקבע מופעלת השיטה )ומשם בסריקה מלמטה למעלה לפי היררכית ההורשה( -
.שיטת הבצל
של המחלקה בה היא מוגדרת. scope נגישה רק בתוך ה-שיטה פרטית3. בו ממוקמת scopeלפי ה-בקריאה לשיטה פרטית, הקוד המופעל נקבע
הקריאה.
)ללא אופרטור ע"י גישה ישירה )קריאה או השמה(, שדהבגישה ל4. בו ממוקמת הגישה )ומשם scopeלפי ה-השייכות(, הגישה לשדה נקבעת
בסריקה מלמטה למעלה לפי היררכית ההורשה(.
, ע"י אופרטור השייכות )קריאה או השמה( שאינו פרטי, שדהבגישה ל5. ) )reference typeבהתאם למחלקת טיפוס המשתנההגישה נקבעת
שעליה שייך השדה )ומשם בסריקה מלמטה למעלה לפי היררכית ההורשה(.
9
למה זה הגיוני?לשיטה פרטית לא ניתן לקרוא ממחלקה אחרת, לכן אם מנסים
להפעיל שיטה פרטית, יש רק מקום אחד שבו אפשר לחפש אותה.
דוגמה להורשה
)שאלה ממבחן(
10
A a = new A (1);A b = new B (2, 22);
System.out.println)a.getX)((; System.out.println)b.getX)((; System.out.println)b.superX)((;
122 Compilation Error !! )The method superX)(
is undefined for the type A(
Output / Notes
if )b instanceof B( System.out.println)b.superX)((; Compilation Error !!
11
public class A {private int x;public int y;public A)int x( {
this.x = x;this.y = 2*x;
}public int getX)( { return x; }public int doubleX)( { return 2 * getX)(; }public int tripleX)( { return 3 * x; }private int subXhelper)( { return x - 1; }public int subX)( {
return subXhelper)(; }
}
public class B extends A {private int x;public int y;public B)int xA, int xB( {
super)xA(;this.x = xB;this.y = xA + xB;
}public int getX)( { return x; }public int superX)( {
return super.getX)(;}public int tenTimesX)( { return 10*x; }private int subXhelper)( { return x-2; }
}
A a = new A (1);A b = new B (2, 22); Output / Notes
12
public class A {private int x;public int y;public A)int x( {
this.x = x;this.y = 2*x;
}public int getX)( { return x; }public int doubleX)( { return 2 * getX)(; }public int tripleX)( { return 3 * x; }private int subXhelper)( { return x - 1; }public int subX)( {
return subXhelper)(; }
}
public class B extends A {private int x;public int y;public B)int xA, int xB( {
super)xA(;this.x = xB;this.y = xA + xB;
}public int getX)( { return x; }public int superX)( {
return super.getX)(;}public int tenTimesX)( { return 10*x; }private int subXhelper)( { return x-2; }
}
B bb = )B(b;System.out.println)bb.superX)((; 2
System.out.println)))B(b(.superX)((; 2System.out.println)a.tripleX)((;System.out.println)b.tripleX)((;
36
System.out.println)b.subX)((;
System.out.println)))B(b(.tenTimesX)((; System.out.println)b.doubleX)((;
22044
113
public class A {private int x;public int y;public A)int x( {
this.x = x;this.y = 2*x;
}public int getX)( { return x; }public int doubleX)( { return 2 * getX)(; }public int tripleX)( { return 3 * x; }private int subXhelper)( { return x - 1; }public int subX)( {
return subXhelper)(; }
}
public class B extends A {private int x;public int y;public B)int xA, int xB( {
super)xA(;this.x = xB;this.y = xA + xB;
}public int getX)( { return x; }public int superX)( {
return super.getX)(;}public int tenTimesX)( { return 10*x; }private int subXhelper)( { return x-2; }
}
System.out.println)))B(a(.tenTimesX)((; Run-time Error: ClassCastException: A cannot be cast to B
Output / Notes
A a = new A (1);A b = new B (2, 22);
14
public class A {private int x;public int y;public A)int x( {
this.x = x;this.y = 2*x;
}public int getX)( { return x; }public int doubleX)( { return 2 * getX)(; }public int tripleX)( { return 3 * x; }private int subXhelper)( { return x - 1; }public int subX)( {
return subXhelper)(; }
}
public class B extends A {private int x;public int y;public B)int xA, int xB( {
super)xA(;this.x = xB;this.y = xA + xB;
}public int getX)( { return x; }public int superX)( {
return super.getX)(;}public int tenTimesX)( { return 10*x; }private int subXhelper)( { return x-2; }
}
Output / NotesA a = new A (1);A b = new B (2, 22);
System.out.println)a.y(; System.out.println)b.y(; System.out.println)))B(b(.y(; B bb= )B(b;System.out.println)bb.y(;System.out.println)))A(bb(.y(;
2424
244
מחלקות אבסטרקטיות
כאשר רוצים לחלוק קוד משותף בין מספר מחלקות למרות •שאין רצון לאפשר יצירת אובייקטים ממחלקת האב.
מחלקת האב:•מכילה קוד משותף.–קובעת אילו שיטות אבסטרקטית על תתי המחלקות לממש.–
תת-מחלקה קונקרטית מממשת שיטות אבסטרקטיות.•
15
מחלקות אבסטרקטיותpublic abstract class <name> {
public abstract void <method name> ( ... );…
}
במחלקה אבסטרקטית יכולות להיות שיטות רגילות, כמו בכל •מחלקה.
להיות לה שיטות אבסטרקטיות: שיטות יכולותבנוסף •שההגדרה שלהן קיימת אבל אין להן מימוש.
אנו מכריזים על מחלקה או על שיטה כאבסטרקטית בעזרת •.abstractהמילה השמורה
16
מחלקות אבסטרקטיותמחלקה אבסטרקטית - לא ניתן ליצור ממנה מופעים.•
public abstract class Game { public Game} … { )(
…}
Game g = new Game(); // Compilation error!
מחלקה שמרחיבה מחלקה אבסטרקטית ולא מממשת את כל • להיות אבסטרקטית בעצמה.חייבתהשיטות האבסטרקטיות,
17
•Spy Robot רובוט מעקב( הינו רובוט הנשלט מרחוק( ומאפשר צילום תמונות ושליחתן.
רובוט מעקב יכול לבצע את הפעולות הבאות:•לצלם תמונות ולשדר אותן–לזוז קדימה / אחורה–להסתובב ימינה / שמאלה–
18
Spy Robot
רובוטי מעקב2נסתכל על •
שניהם יכולים לצלם תמונות ולשדר באותה דרך אך •הם זזים בדרכים שונות.
19
Spy Robot
20
Spy Robotpublic abstract class SpyRobot {
private String model;public SpyRobot(String model) {
this.model=model;}public String getModel() {
return this.model;}
public abstract void moveForward();public abstract void moveBackward();public abstract void turnLeft();public abstract void turnRight();
public void takePicture() { ... }public void chargeBattery() { ... }
}
21
Roboquad – Spy Robotpublic class LegsSpyRobot extends SpyRobot {
public LegsSpyRobot() {super("Roboquad");
}
public void moveForward() {for(int i=0; i<4; i++)
this.moveLeg(i, 1);}public void moveBackward() {
for(int i=0; i<4; i++)this.moveLeg(i, -1);
}
public void turnLeft() {this.moveLeg(0,-1);this.moveLeg(1,-1);this.moveLeg(2,1);this.moveLeg(3,1);
}// direction {1=forward, -1=backward}private void moveLeg(int legId, int dir) { ... };
}
public void turnRight() {this.moveLeg(0,1);this.moveLeg(1,1);this.moveLeg(2,-1);this.moveLeg(3,-1);
}
0
12
3
22
Spyke – Spy Robotpublic class WheelsSpyRobot extends SpyRobot {
public WheelsSpyRobot() {super("Spyke");
}
public void moveForward() { this.turnWheels(1,1);
}public void moveBackward() {
this.turnWheels(-1,-1); }
public void turnLeft() { this.turnWheels(0,-1);
}public void turnRight() {
this.turnWheels(-1,0); }
// direction {1=forward, 0=stop, -1=backward}private void turnWheels(int rightDir,int leftDir) { ... };// move featurespublic void waveHands() { ... }
}
23
Fly – Spy Robot
האם את זה אתם כבר יכולים לממש לבד ?
מחלקה אבסטרקטית ממשק
לא ניתן ליצור מופעים לא ניתן ליצור מופעים
(extendsשימוש ע"י ירושה ) ( implementsשימוש ע"י מימושו )
יכולה להכיל קוד של חלק מהשיטות הכרזה של שיטות בלי מימוש
יורשי מחלקה זו יהיו בעלי קוד משותף וכן בעלי התנהגויות שונות )השיטות
האבסטרקטיות(
ממשק הוא הכרזה על תכונה מופשטת, למממשים אין קוד
משותף.
מחלקה יכולה לרשת מחלקה )אבסטרקטית( אחת בלבד
מחלקה יכולה לממש מספר ממשקים
אין הגבלה על שדות (implicitlyרק קבועים סטאטיים )
24
נממש משחקים מתורת המשחקים ע"י הורשה:•משחק מוגדר על ידי מערכת של פעולות אפשריות –
ושיטת ניקוד.במשחק משחקים שני שחקנים כאשר שני –
השחקנים בוחרים פעולה בו-זמנית.בהינתן שתי הבחירות של השחקנים יקבלו –
השחקנים ניקוד ע"פ בחירתם.
25
דוגמא נוספת
דוגמה: אבן נייר ומספריים
בחירה מבין שלוש הפעולות האפשריות )אבן, •נייר או מספריים(.
אבן שוברת מספריים.–מספריים גוזרים נייר.–נייר עוטף אבן.–
26http://www.youtube.com/watch?v=_PUEoDYpUyQ
דוגמה: דילמת האסירהמשטרה עוצרת שני עבריינים שביצעו פשע משותף, ומפרידה •
ביניהם לצורך חקירה.המשטרה מציעה לכל אחד מהם להעיד נגד רעהו, וכפרס מובטח •
לעד עונש מופחת.בחירה מבין הפעולות האפשריות: להעיד או לשתוק.•ניקוד:•
אם שניהם יעידו, ייכנס כל אחד מהם לכלא לחמש שנים.– 15אם רק אחד מהם יעיד ורעהו ישתוק, העד יצא מיד לחופשי וחברו ייכלא ל-–
שנה.אם שניהם ישתקו, יכנס כל אחד מהם לשנה בכלא.–
27
המחלקות שעלינו לממשActionפעולה •
שם הפעולה )"אבן"(–Playerשחקן •
"(Andrea Farinaשם השחקן )" –מספר נקודות–בחירת פעולה )מהלך( מתוך קבוצת פעולות אפשריות.–
Gameמשחק •קבוצת פעולות אפשריות –שיטת ניקוד– שחקנים2 – שם המשחק–
28
מימוש המחלקה של פעולה כלליתpublic class Action {
private String name;
public Action(String name) {this.name = name;
}public String getName(){
return this.name;}public boolean equals(Object other) {
boolean ans = false;if(other instanceof Action) ans =
this.name.equals(((Action)other).name);return ans;
}
}29
מימוש המחלקה של שחקן כלליpublic abstract class Player {
private String name;private int score;
public Player(String name){this.name = name;this.score = 0;
}
public abstract Action selectAction(Action[] actions);
public boolean isWinner(Player p){return (this.score > p.getScore());
}
public void updateScore(int score){this.score = this.score + score;
}
public int getScore(){ return this.score;
}} 30
מימוש שחקן אקראי
public class RandomPlayer extends Player{
public RandomPlayer(String name) {super(name);
}
public Action selectAction(Action[] actions){int randIdx = (int)
(Math.random()*actions.length);return actions[randIdx];
}}
31
מימוש שחקן עיקבי
public class ConsecutivePlayer extends Player {
private int lastIdx;
public ConsecutivePlayer(String name) {super(name);this.lastIdx = 0;
}
public Action selectAction(Action[] actions) {this.lastIdx = (this.lastIdx + 1) %
actions.length;return actions[this.lastIdx];
}}
32
33
public abstract class Game {
private Player p1, p2;private String name; //game nameprotected Action[] actions; // the set of actions
public Game(Player p1, Player p2, String name){this.p1 = p1; this.p2 = p2; this.name = name;this.initActions();
}
// There is no real list of actions in a general game protected abstract void initActions();
…
משחק כללימימוש
public abstract class Game {…
public void play(int turnCount) {for (int i=0; i<turnCount; i=i+1)
this.playSingleTurn();}
private void playSingleTurn() {/* the selection order is not important * as each player does not * know the choice of the other player */Action a1 = this.p1.selectAction(actions);Action a2 = this.p2.selectAction(actions);this.rewardPlayers(a1, a2);
}// There is no real scoring strategy in a general game protected abstract void rewardPlayers(Action a1, Action a2);
… 34
)המשך(משחק כללימימוש
public abstract class Game {…
public Player getWinner () {if (this.p1.isWinner(this.p2))
return this.p1; else
return this.p2;}
protected Player getFirstPlayer() {return this.p1;
}
protected Player getSecondPlayer() {return this.p2;
}}
35
)המשך(משחק כללימימוש
מימוש המשחק אבן נייר ומספרייםpublic class RockPaperScissors extends Game{
public RockPaperScissors(Player p1, Player p2) {super(p1, p2, "Rock Paper Scissors");
}
protected void initActions(){this.actions = new Action[3];this.actions[0] = new Action("rock");this.actions[1] = new Action("paper");this.actions[2] = new Action("scissors");
}
...
36
37
protected void rewardPlayers(Action a1, Action a2) {int p1score = 0;if (!(a1.equals(a2))) {// Different actions
if ((a1.getName().equals("rock") &&a2.getName().equals("scissors"))
|| (a1.getName().equals("paper") && a2.getName().equals("rock"))
|| (a1.getName().equals("scissors") &&a2.getName().equals("paper"))) {
p1score = 1;} else {
p1score = -1;}
}this.getFirstPlayer().updateScore(p1score);this.getSecondPlayer().updateScore(-p1score);
}}
מימוש המשחק דילמת האסיר
public class PrisonerDilemmas extends Game{
public PrisonerDilemmas(Player p1, Player p2) {super(p1, p2, "Prisoner's Dilemma");
}
protected void initActions(){ this.actions = new Action[2];this.actions[0] = new Action("silent");this.actions[1] = new Action("blame");
}...
38
protected void rewardPlayers(Action a1, Action a2) {if (a1.equals(a2)) { // Same actions
if (a1.getName().equals("blame") { // blame & blame
this.getFirstPlayer().updateScore(-5);
this.getSecondPlayer().updateScore(-5);} else { // silent & silent
this.getFirstPlayer().updateScore(-1);
this.getSecondPlayer().updateScore(-1);}
} else { // Different actionsif (a1.getName().equals("blame") { //
blame & silent
this.getFirstPlayer().updateScore(0);
this.getSecondPlayer().updateScore(-15);} else { // silent & blame
this.getFirstPlayer().updateScore(-15);
this.getSecondPlayer().updateScore(0);}
}}
}
39