slide1 n.
Download
Skip this Video
Download Presentation
בתרגול הקודם

Loading in 2 Seconds...

play fullscreen
1 / 46

בתרגול הקודם - PowerPoint PPT Presentation


  • 165 Views
  • Uploaded on

בתרגול הקודם. הורשה: ניתן להרחיב רק מחלקה אחת כל מה שלא private – עובר בהורשה המילה השמורה super יצירת היררכיה Object היא שורש ההיררכיה דריסה אופרטור instanceof המחלקה Object השיטות toString , equals פולימורפיזם חד כיווניות. תרגול 11. המשך תכנות מונחה עצמים. היום בתרגול.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'בתרגול הקודם' - brie


Download Now An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide1
בתרגול הקודם
  • הורשה:
    • ניתן להרחיב רק מחלקה אחת
    • כל מה שלא private – עובר בהורשה
    • המילה השמורה super
    • יצירת היררכיה
    • Object היא שורש ההיררכיה
    • דריסה
  • אופרטור instanceof
  • המחלקה Object
    • השיטות toString, equals
  • פולימורפיזם
    • חד כיווניות
slide2

תרגול 11

המשך תכנות מונחה עצמים

slide3
היום בתרגול
  • כללי הרשאות בהורשה
  • חריגות
  • מחלקות אבסטרקטיות
visibility modifiers
כללי הרשאות (visibility modifiers) בהורשה

public– שדות ושיטות המוגדרים כ-public ניתנים לגישה מתוך ומחוץ למחלקה.

protected– שדות ושיטות המוגדרים כ-protectedניתנים לגישה מתוך המחלקה וממחלקות היורשות מהמחלקה, אך אינם ניתן לגישה ממחלקות אחרות *.

(* ממחלקות אחרות הנמצאות ב package אחר. protected מתנהג כמו public באותו package)

private – שדות ושיטות המוגדרים כ-private אינם ניתנים לגישה מחוץ למחלקה.ניסיון לגשת לשדה או שיטה כזו מחוץ למחלקה יעורר שגיאת קומפילציה.

slide5

כללי הרשאות (visibility modifiers) בהורשה

  • שיטות לא יכולות להידרס ע"י שיטה מרמת שיתוף נמוכה יותר, זו שגיאת קומפילציה. כלומר:
    • לא ניתן לדרוס שיטה public עם protected או private
    • לא ניתן לדרוס שיטה protected עם שיטה private

public classBook {

public String getName() {

}

}

public classDictionary extends Book {

protected String getName() {

}

}

Compilation Error

שאלה: מה ההיגיון מאחורי שגיאה זו?

בלעדיה הייתה מתקבלת סתירה לעקרון הפולימורפיזם

Book b = new Dictionary();

System.out.println (b.getName() );

visibility modifiers1
כללי הרשאות (visibility modifiers) בהורשה
  • משתנים אינם עוברים דריסה בהורשה.
  • שיטות שאינן private עוברות בהורשה.
    • שיטות פרטיות נועדו למימוש פנימי של מחלקת האב, ואינן ניתנות לשימוש ע"י תת מחלקה.
    • תת-המחלקה לא מכירה את המשתנים והשיטות הפרטיים של המחלקת האב, ממנה היא יורשת, ולכן עשויה גם להכריז על משתנים ושיטות פרטיים בעלי אותו שם וחתימה.
  • דוגמה:
    • חנות היא סוג של עסק
      • עסק: דמי שכירות, עובדים, הוצאות חודשיות
      • חנות: פריטי סחורה, הוצאות חודשיות הכוללות אחזקת מלאי.
    • כל מחלקה מומשה ע"י מתכנתת אחרת
    • בכל מחלקה מימוש שונה לשיטה פרטית - calcSum()
slide7

publicclass Business {

protected Employee[] employees;

protecteddoublemonthlyRent;

......

// calculates total monthly expenses

publicdoublemonthlyExpenses() {

double salaries = calcSum();

returnthis.monthlyRent + salaries;

}

// calculates monthly salaries

privatedoublecalcSum() {

double sum = 0;

for (inti=0; i<this.employees.length; i=i+1) {

sum = sum + this.employees[i].getSalary();

}

return sum;

}

......

}

 קריאה לשיטה פרטית

slide8

public class Shop extends Business {

protected Item[] items;

......

// override: calculates total monthly expenses

publicdoublemonthlyExpenses() {

doubleitemPrices = calcSum();

returnitemPrices + super.monthlyExpenses();

}

// No override: calculates total item prices

privatedoublecalcSum() {

double sum=0;

for (inti=0; i<this.items.length; i=i+1) {

sum = sum + this.items[i].getPrice();

}

return sum;

}

......

}

 קריאה לשיטה פרטית

שאלה: אם נשנה את המאפיין של calcSum ל-protected , מה תחשב monthlyExpenses?

slide9
סיכום חוקי גישה לשיטות ושדות בהורשה ב-Java:
  • טיפוס המשתנה (טיפוס המצביע/ reference type) קובע בזמן הידור אילו שיטות ניתן להפעיל על המשתנה ולאילו שדות של המשתנה ניתן לגשת.
  • בקריאה לשיטה שאינה פרטית המופיעה במחלקת-אב ובתת-מחלקה, אם ע"י קריאה ישירה או ע"י שימוש באופרטור השייכות (.), הקוד המופעל נקבע בהתאם למחלקת האובייקט בפועלinstance type) ) שעליו מופעלת השיטה (ומשם בסריקה מלמטה למעלה לפי היררכית ההורשה) - שיטת הבצל.
  • שיטה פרטית נגישה רק בתוך ה-scope של המחלקה בה היא מוגדרת. בקריאה לשיטה פרטית, הקוד המופעל נקבע לפי ה-scope בו ממוקמת הקריאה.
  • בגישה לשדה (קריאה או השמה), ע"י גישה ישירה (ללא אופרטור השייכות), הגישה לשדה נקבעת לפי ה-scope בו ממוקמת הגישה (ומשם בסריקה מלמטה למעלה לפי היררכית ההורשה).
  • בגישה לשדה (קריאה או השמה) שאינו פרטי, ע"י אופרטור השייכות, הגישה נקבעת בהתאם למחלקת טיפוס המשתנהreference type) ) שעליה שייך השדה (ומשם בסריקה מלמטה למעלה לפי היררכית ההורשה).
  • למה זה הגיוני?
  • לשיטה פרטית לא ניתן לקרוא ממחלקה אחרת, לכן אם מנסים להפעיל שיטה פרטית, יש רק מקום אחד שבו אפשר לחפש אותה.
slide10
דוגמה להורשה

(שאלה ממבחן)

slide11

publicclass A {

privateintx;

publicinty;

public A(int x) {

this.x = x;

this.y = 2*x;

}

publicintgetX() { returnx; }

publicintdoubleX() { return 2 * getX(); }

publicinttripleX() { return 3 * x; }

privateintsubXhelper() { returnx - 1; }

publicintsubX() {

returnsubXhelper();

}

}

publicclass B extends A {

privateintx;

publicinty;

public B(intxA, intxB) {

super(xA);

this.x = xB;

this.y = xA + xB;

}

publicintgetX() { returnx; }

publicintsuperX() {

returnsuper.getX();

}

publicinttenTimesX() { return 10*x; }

privateintsubXhelper() { returnx-2; }

}

A a = new A (1);

A b = new B (2, 22);

Output / Notes

System.out.println(a.getX());

System.out.println(b.getX());

System.out.println(b.superX());

1

22

Compilation Error !!(The method superX() is undefined for the type A)

if (b instanceof B)

System.out.println(b.superX());

Compilation Error !!

slide12

publicclass A {

privateintx;

publicinty;

public A(int x) {

this.x = x;

this.y = 2*x;

}

publicintgetX() { returnx; }

publicintdoubleX() { return 2 * getX(); }

publicinttripleX() { return 3 * x; }

privateintsubXhelper() { returnx - 1; }

publicintsubX() {

returnsubXhelper();

}

}

publicclass B extends A {

privateintx;

publicinty;

public B(intxA, intxB) {

super(xA);

this.x = xB;

this.y = xA + xB;

}

publicintgetX() { returnx; }

publicintsuperX() {

returnsuper.getX();

}

publicinttenTimesX() { return 10*x; }

privateintsubXhelper() { returnx-2; }

}

A a = new A (1);

A b = new B (2, 22);

Output / Notes

B bb = (B)b;

System.out.println(bb.superX());

2

System.out.println(((B)b).superX());

2

System.out.println(a.tripleX());

System.out.println(b.tripleX());

3

6

slide13

publicclass A {

privateintx;

publicinty;

public A(int x) {

this.x = x;

this.y = 2*x;

}

publicintgetX() { returnx; }

publicintdoubleX() { return 2 * getX(); }

publicinttripleX() { return 3 * x; }

privateintsubXhelper() { returnx - 1; }

publicintsubX() {

returnsubXhelper();

}

}

publicclass B extends A {

privateintx;

publicinty;

public B(intxA, intxB) {

super(xA);

this.x = xB;

this.y = xA + xB;

}

publicintgetX() { returnx; }

publicintsuperX() {

returnsuper.getX();

}

publicinttenTimesX() { return 10*x; }

privateintsubXhelper() { returnx-2; }

}

A a = new A (1);

A b = new B (2, 22);

Output / Notes

Run-time Error:

ClassCastException: A cannot be cast to B

System.out.println(((B)a).tenTimesX());

System.out.println(((B)b).tenTimesX());

System.out.println(b.doubleX());

220

44

System.out.println(b.subX());

1

slide14

publicclass A {

privateintx;

publicinty;

public A(int x) {

this.x = x;

this.y = 2*x;

}

publicintgetX() { returnx; }

publicintdoubleX() { return 2 * getX(); }

publicinttripleX() { return 3 * x; }

privateintsubXhelper() { returnx - 1; }

publicintsubX() {

returnsubXhelper();

}

}

publicclass B extends A {

privateintx;

publicinty;

public B(intxA, intxB) {

super(xA);

this.x = xB;

this.y = xA + xB;

}

publicintgetX() { returnx; }

publicintsuperX() {

returnsuper.getX();

}

publicinttenTimesX() { return 10*x; }

privateintsubXhelper() { returnx-2; }

}

A a = new A (1);

A b = new B (2, 22);

Output / Notes

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);

2

4

24

24

4

exceptions
חריגות (Exceptions)

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

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

runtimeexceptions
כבר נתקלנו ב-RuntimeExceptions

וראינו כי ניתן לזרוקRuntimeException באמצעות throw

ArithmeticException:

ניסיון חלוקה באפס

IndexOutOfBoundsException: חריגה ממערך

NullPointerException:

ניסיון לפעול על משתנה שאינו פרימיטיבי בעל ערך null

throw runtimeexception
Throw RuntimeException

publicclass Car {

privatefinalint MAX_SPEED = 210;

privatefinalint MIN_SPEED = -20;

privateint speed;

publicvoidsetSpeed(int speed){

if ((speed >= MIN_SPEED) && (speed <= MAX_SPEED))

this.speed= speed;

else

thrownewRuntimeException(“Illegal speed”);

}

}

publicstaticvoid main(String[] args) {

Car car = new Car();

car.setSpeed(300);

}

Output: Exception in thread "main" java.lang.RuntimeException: Illegal Speed

at Car.setSpeed(Car.java:11)

at Car.main(Car.java:17)

exceptions1
סוגי Exceptions

Object

Exception

IOException

RuntimeException

NullPointerException

exception
Exception
  • ניתן לייצר חריגהע"י פקודת throwהמייצרת את אירוע החריגה.
  • ישנן שתי דרכים לטפל בחריגה:
    • לתפוס את ה- Exception על ידי שימוש במילים השמורות tryו-catch
    • להעביר את ה- Exception הלאה על ידי שימוש במילה השמורה throwsבכותרת הפונקציה שאנו כותבים.

(טיפול בחריגות לא הכרחי עבור (RuntimeExceptions

throw and catch exceptions
Throw and Catch Exceptions

publicclass Car {

privatefinalint MAX_SPEED = 210;

privatefinalint MIN_SPEED = -20;

privateint speed;

publicvoidsetSpeed(int speed) throws Exception {

if ((speed >= MIN_SPEED) && (speed <= MAX_SPEED))

this.speed = speed;

else

thrownew Exception(“Illegal speed”);

}

}

publicstaticvoid main(String[] args) {

Car car = new Car();

car.setSpeed(100);

}

Compilation Error

throw and catch exceptions1
Throw and Catch Exceptions

publicclass Car {

privatefinalint MAX_SPEED = 210;

privatefinalint MIN_SPEED = -20;

privateint speed;

publicvoidsetSpeed(int speed) throws Exception {

if ((speed >= MIN_SPEED) && (speed <= MAX_SPEED))

this.speed = speed;

else

thrownew Exception(“Illegal speed”);

}

}

publicstaticvoid main(String[] args) {

Car car = new Car();

try{

car.setSpeed(300);

System.out.println("Broke the speed limit !");

} catch(Exception e){

System.err.println("Caught Exception: "+e.getMessage());

}

System.out.println("Current speed is "+car.getSpeed()+” km/h);

}

Output: Caught Exception: Illegal Speed

Current speed is 0 km/h

slide22
מחלקות אבסטרקטיות
  • כאשר רוצים לחלוק קוד משותף בין מספר מחלקות למרות שאין רצון לאפשר יצירת אובייקטים ממחלקת האב.
  • מחלקת האב:
    • מכילה קוד משותף.
    • קובעת אילו שיטות אבסטרקטית על תתי המחלקות לממש.
  • תת-מחלקה קונקרטית מממשת שיטות אבסטרקטיות.
slide23
מחלקות אבסטרקטיות

public abstractclass<name> {

public abstractvoid <method name> ( ... );

}

  • במחלקה אבסטרקטית יכולות להיות שיטות רגילות, כמו בכל מחלקה.
  • בנוסף יכולות להיות לה שיטות אבסטרקטיות: שיטות שההגדרה שלהן קיימת אבל אין להן מימוש.
  • אנו מכריזים על מחלקה או על שיטה כאבסטרקטית בעזרת המילה השמורה abstract.
slide24
מחלקות אבסטרקטיות
  • מחלקה אבסטרקטית - לא ניתן ליצור ממנה מופעים.

publicabstractclass Game {

public Game() { … }

}

Game g = new Game(); // Compilation error!

  • מחלקה שמרחיבה מחלקה אבסטרקטית ולא מממשת את כל השיטות האבסטרקטיות, חייבת להיות אבסטרקטית בעצמה.
spy robot
Spy Robot
  • Spy Robot (רובוט מעקב) הינו רובוט הנשלט מרחוק ומאפשר צילום תמונות ושליחתן.
  • רובוט מעקב יכול לבצע את הפעולות הבאות:
    • לצלם תמונות ולשדר אותן
    • לזוז קדימה / אחורה
    • להסתובב ימינה / שמאלה
spy robot1
Spy Robot
  • נסתכל על 2 רובוטי מעקב
  • שניהם יכולים לצלם תמונות ולשדר באותה דרך אך הם זזים בדרכים שונות.
spy robot2
Spy Robot

publicabstractclass SpyRobot {

private String model;

public SpyRobot(String model) {

this.model=model;

}

public String getModel() {

returnthis.model;

}

publicabstractvoid moveForward();

publicabstractvoid moveBackward();

publicabstractvoid turnLeft();

publicabstractvoid turnRight();

publicvoid takePicture() { ... }

publicvoid chargeBattery() { ... }

}

roboquad spy robot
Roboquad – Spy Robot

publicclassLegsSpyRobotextendsSpyRobot {

publicLegsSpyRobot() {

super("Roboquad");

}

publicvoidmoveForward() {

for(inti=0; i<4; i++)

this.moveLeg(i, 1);

}

publicvoidmoveBackward() {

for(inti=0; i<4; i++)

this.moveLeg(i, -1);

}

publicvoidturnLeft() {

this.moveLeg(0,-1);

this.moveLeg(1,-1);

this.moveLeg(2,1);

this.moveLeg(3,1);

}

// direction {1=forward, -1=backward}

privatevoidmoveLeg(intlegId, intdir) { ... };

}

3

1

2

0

publicvoid turnRight() {

this.moveLeg(0,1);

this.moveLeg(1,1);

this.moveLeg(2,-1);

this.moveLeg(3,-1);

}

spyke spy robot
Spyke – Spy Robot

publicclassWheelsSpyRobotextendsSpyRobot {

publicWheelsSpyRobot() {

super("Spyke");

}

publicvoidmoveForward() {

this.turnWheels(1,1);

}

publicvoidmoveBackward() {

this.turnWheels(-1,-1);

}

publicvoidturnLeft() {

this.turnWheels(0,-1);

}

publicvoidturnRight() {

this.turnWheels(-1,0);

}

// direction {1=forward, 0=stop, -1=backward}

privatevoidturnWheels(intrightDir,intleftDir) { ... };

// move features

publicvoidwaveHands() { ... }

}

fly spy robot
Fly – Spy Robot

האם את זה אתם כבר יכולים לממש לבד ?

slide32
דוגמא נוספת
  • נממש משחקים מתורת המשחקים ע"י הורשה:
    • משחק מוגדר על ידי מערכת של פעולות אפשריות ושיטת ניקוד.
    • במשחק משחקים שני שחקנים כאשר שני השחקנים בוחרים פעולה בו-זמנית.
    • בהינתן שתי הבחירות של השחקנים יקבלו השחקנים ניקוד ע"פ בחירתם.
slide33
דוגמה: אבן נייר ומספריים
  • בחירה מבין שלוש הפעולות האפשריות (אבן, נייר או מספריים).
    • אבן שוברת מספריים.
    • מספריים גוזרים נייר.
    • נייר עוטף אבן.
  • http://www.youtube.com/watch?v=_PUEoDYpUyQ
slide34
דוגמה: דילמת האסיר
  • המשטרה עוצרת שני עבריינים שביצעו פשע משותף, ומפרידה ביניהם לצורך חקירה.
  • המשטרה מציעה לכל אחד מהם להעיד נגד רעהו, וכפרס מובטח לעד עונש מופחת.
  • בחירה מבין הפעולות האפשריות: להעיד או לשתוק.
  • ניקוד:
    • אם שניהם יעידו, ייכנס כל אחד מהם לכלא לחמש שנים.
    • אם רק אחד מהם יעיד ורעהו ישתוק, העד יצא מיד לחופשי וחברו ייכלא ל-15 שנה.
    • אם שניהם ישתקו, יכנס כל אחד מהם לשנה בכלא.
slide35
המחלקות שעלינו לממש
  • פעולה Action
    • שם הפעולה ("אבן")
  • שחקן Player
    • שם השחקן (" Andrea Farina ")
    • מספר נקודות
    • בחירת פעולה (מהלך) מתוך קבוצת פעולות אפשריות.
  • משחק Game
    • קבוצת פעולות אפשריות
    • שיטת ניקוד
    • 2 שחקנים
    • שם המשחק
slide36
מימוש המחלקה של פעולה כללית

publicclass Action {

private String name;

public Action(String name) {

this.name = name;

}

public String getName(){

returnthis.name;

}

publicboolean equals(Object other) {

booleanans = false;

if(other instanceof Action)

ans = this.name.equals(((Action)other).name);

returnans;

}

}

slide37
מימוש המחלקה של שחקן כללי

publicabstractclass Player {

private String name;

privateintscore;

public Player(String name){

this.name = name;

this.score = 0;

}

publicabstract Action selectAction(Action[] actions);

publicbooleanisWinner(Player p){

return (this.score > p.getScore());

}

publicvoidupdateScore(int score){

this.score = this.score + score;

}

publicintgetScore(){

returnthis.score;

}

}

slide38
מימוש שחקן אקראי

publicclass RandomPlayer extends Player{

public RandomPlayer(String name) {

super(name);

}

public Action selectAction(Action[] actions){

int randIdx = (int)(Math.random()*actions.length);

return actions[randIdx];

}

}

slide39
מימוש שחקן עיקבי

publicclass ConsecutivePlayer extends Player {

privateintlastIdx;

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];

}

}

slide40

מימוש משחק כללי

publicabstractclass Game {

private Player p1, p2;

private String name; //game name

protected 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

protectedabstractvoid initActions();

slide41

מימוש משחק כללי (המשך)

publicabstractclass Game {

publicvoid play(intturnCount) {

for (inti=0; i<turnCount; i=i+1)

this.playSingleTurn();

}

privatevoidplaySingleTurn() {

/* 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

protectedabstractvoidrewardPlayers(Action a1, Action a2);

slide42

מימוש משחק כללי (המשך)

publicabstractclass Game {

public Player getWinner () {

if (this.p1.isWinner(this.p2))

returnthis.p1;

else

returnthis.p2;

}

protected Player getFirstPlayer() {

returnthis.p1;

}

protected Player getSecondPlayer() {

returnthis.p2;

}

}

slide43
מימוש המשחק אבן נייר ומספריים

publicclass RockPaperScissors extends Game{

public RockPaperScissors(Player p1, Player p2) {

super(p1, p2, "Rock Paper Scissors");

}

protectedvoid initActions(){

this.actions = new Action[3];

this.actions[0] = new Action("rock");

this.actions[1] = new Action("paper");

this.actions[2] = new Action("scissors");

}

...

slide44

protectedvoidrewardPlayers(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);

}

}

slide45
מימוש המשחק דילמת האסיר

publicclass PrisonerDilemmas extends Game{

public PrisonerDilemmas(Player p1, Player p2) {

super(p1, p2, "Prisoner's Dilemma");

}

protectedvoid initActions(){

this.actions = new Action[2];

this.actions[0] = new Action("silent");

this.actions[1] = new Action("blame");

}

...

slide46

protectedvoidrewardPlayers(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 actions

if (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);

}

}

}

}

ad