ps9

‫תרגול מספר ‪9‬‬
‫‪1‬‬
‫אז מה נלמד היום?‬
‫• שעה ראשונה‬
‫– ממשקים ‪Interfaces‬‬
‫• שעה שנייה‪:‬‬
‫– מחלקות אבסטקטיות ‪abstract class‬‬
‫‪2‬‬
Interface
• Is a way for the coder to tell the compiler:
“limit me, make me work by the contract”.
• An interface is similar to a class but has many differences and
is used for different reasons.
• An interface declares public variables and methods,
but does not implement them.
• An interface will be implemented by classes.
Interface: example
public interface Predator
{
boolean chasePrey(Prey p);
void eatPrey(Prey p);
}
For example, a cat is a predator
because it eats mice.
A frog is also a predator
because it eats bugs.
So we will have:
public class Cat implements Predator
{
public boolean chasePrey(Prey p)
{
// code to chase prey p
// (specifically for a cat)
run();
}
public void eatPrey (Prey p)
{
// code to eat prey p
// (specifically for a cat)
chew(p);
swallow(p);
}
…
}
Interface: example
public interface Predator
{
boolean chasePrey(Prey p);
void eatPrey(Prey p);
}
public class Frog implements Predator
{
public boolean chasePrey(Prey p) {
// code to chase prey p
// (specifically for a frog)
jump();
}
public void eatPrey (Prey p) {
// code to eat prey p
// (specifically for a frog)
swallow(p);
}
*Remember: you cannot create an
object from an interface.
…
}
Interface
Another example –
public interface Vehicle {
public void startEngine();
public void honk();
public void drive(int speed);
}
A car is a vehicle.
A motorcycle is a vehicle.
A bus is a vehicle.
Interface
public interface Vehicle {
public void startEngine();
public void honk();
public void drive(int speed);
}
*Notice that Car has
a variable of its own (numOfDoors)
that not all vehicles will have.
For example,
a motorcycle does not have doors
So the variable is unnecessary
for the Motorcycle class.
public class Car implements Vehicle {
private int numOfDoors;
//Constructor:
public Car() {
numOfDoors = 4;
}
public void startEngine() {
//code to start the engine of a car
turnKey();
}
void honk(){
System.out.println (“beep beep”)
}
void drive(int speed) {
//code to drive specific for a car
}
}
Interface
public interface Vehicle {
public void startEngine();
public void honk();
public void drive(int speed);
}
*Notice that the motorcycle class
has an extra method
“popAWheelie”
that can only be done
by motorcycles.
None of the other vehicles
can pop a wheelie.
public class Motorcycle implements Vehicle
{
//constructor
public Motorcycle() {
}
public void startEngine() {
//code to start motorcycle engine
turnKey();
}
void honk(){
System.out.println(“waka waka”)
}
void drive(int speed) {
//code to drive a motorcycle
}
void popAWheelie() {
//code to pop a wheelie
}
}
Interface
public interface Vehicle {
public void startEngine();
public void honk();
public void drive(int speed);
}
*typeOfBus can be
“School Bus”
or
“City Bus”…
public class Bus implements Vehicle {
String typeOfBus;
//constructor
public Bus(String type) {
typeOfBus = type;
}
public void startEngine() {
//code to start the engine of a bus
}
void honk(){
System.out.println(“Blaaaaaaaaah”)
}
void drive(int speed) {
//code to drive specific speed for a bus
}
void ghostRide() {
//code to ghost ride the bus
}
}
Interface
• All variables in an interface are: final static
• Should be used with the syntax: Interface.variable
Interface
Implementing
2 interfaces for 1 class:
interface Inter
{
public int TEST = 3;
public void printTest();
}
interface Inter1
{
public int TEST = 5;
}
class Test implements Inter, Inter1
{
//wrong version:
public void printTest()
{
System.out.print(TEST);
//compiler error even if there was 1 interface
}
}
Interface
Implementing
2 interfaces for 1 class:
interface Inter
{
public int TEST = 3;
public void printTest();
}
interface Inter1
{
public int TEST = 5;
}
automatically: final static
class Test implements Inter, Inter1
{
//correct version:
public void printTest() {
System.out.print(Inter.TEST);
}
}
Interface
Implementing
2 interfaces for 1 class:
interface Inter
{
public int TEST = 3;
public void printTest();
}
interface Inter1
{
public int TEST = 5;
}
automatically: final static
class Test implements Inter, Inter1
{
//correct version:
public void printTest() {
System.out.print(Inter.TEST);
}
}
Class Main{
public static void main(String[] args) {
Inter t = new Test();
Test t2 = new Test();
int x = t.TEST; //wrong usage
int y = ((Inter1)t).TEST //wrong usage
}
Interface
Implementing
2 interfaces for 1 class:
interface Inter
{
public int TEST = 3;
public void printTest();
}
interface Inter1
{
public int TEST = 5;
}
automatically: final static
class Test implements Inter, Inter1
{
//correct version:
public void printTest() {
System.out.print(Inter.TEST);
}
}
Class Main{
public static void main(String[] args) {
Inter t = new Test();
Test t2 = new Test();
int x = Inter.TEST; //correct usage
int y = Inter1.TEST; //correct usage
}
Interface as a contract
public interface OrderedPair
{
//list of methods
public Object getFirst();
public Object getSecond();
public boolean equals(OrderedPair
another);
}
public class Pair implements OrderedPair
{
private Object first, second;
public Pair(Object x, Object y){
first = x;
second = y;
}
public Object getFirst(){
return first;
}
public Object getSecond() {
return second;
}
public boolean equals(OrderedPair another) {
return (first.equals(another.getFirst()) &
second.equals(another.getSecond()) );
}
}
‫… ‪>,‬ממשק ‪>,<2‬ממשק ‪> implements <1‬שם מחלקה< ‪• public class‬‬
‫• על המחלקה לממש את הפונקציות של כל הממשקים‪.‬‬
‫• אם מחלקה מיישמת שני ממשקים בעלי שיטה בעלת שם זהה ‪foo‬‬
‫אז‪:‬‬
‫– אם לשתי ה ‪ foo‬יש חתימה שונה אז המחלקה מיישמת חייבת לממש את‬
‫שתיהן‪.‬‬
‫– אם לשתי ה ‪ foo‬יש אותה חתימה אך טיפוס מוחזר שונה ‪ -‬טעות קומפילציה‪.‬‬
‫(לא ניתן לממש את שני הממשקים יחד)‪.‬‬
‫מחלקות אבסטרקטיות‬
‫• על מנת להבין את הצורך בשימוש במחלקות‬
‫אבסטקטיות נממש משחקים מתורת המשחקים‬
‫ע"י הורשה כפי שלמדנו בתרגול הקודם‪:‬‬
‫‪17‬‬
‫הגדרת המשחק‬
‫• משחק מוגדר על ידי מערכת של פעולות אפשריות‬
‫• במשחק משחקים שני שחקנים כאשר שני‬
‫השחקנים בוחרים פעולה בו‪-‬זמנית‪.‬‬
‫• בהינתן שתי הבחירות של שני השחקנים יקבלו‬
‫השחקנים ניקוד על פי הבחירה המשותפת‪.‬‬
‫‪18‬‬
‫דוגמא למשחק ‪:‬אבן נייר ומספריים‬
‫•‬
‫•‬
‫•‬
‫•‬
‫‪19‬‬
‫שני השחקנים מגלים את בחירתם מבין שלוש‬
‫הפעולות האפשריות (אבן נייר או מספריים) ‪.‬‬
‫אבן שוברת מספריים‪.‬‬
‫מספריים גוזרים נייר‪.‬‬
‫נייר עוטף אבן‪.‬‬
‫דוגמא נוספת למשחק‪:‬דילמת האסיר‬
‫•‬
‫•‬
‫•‬
‫•‬
‫•‬
‫•‬
‫‪20‬‬
‫דוגמא קלאסית מתורת המשחקים‪.‬‬
‫המשטרה עצרה שני עבריינים שביצעו פשע משותף‪ ,‬ומפרידה‬
‫ביניהם לצורך חקירה‪.‬‬
‫למשטרה אין די ראיות להעמידם לדין‪ ,‬ולכן היא מציעה לכל אחד‬
‫מהם להעיד נגד רעהו‪ ,‬וכפרס מובטח לעד עונש מופחת‪.‬‬
‫אם שני האסירים יקבלו את הצעת המשטרה‪ ,‬ייכנס כל אחד מהם‬
‫לכלא לחמש שנים‪.‬‬
‫אם רק אחד מהם יעיד ורעהו ישתוק‪ ,‬העד יצא מיד לחופשי וחברו‬
‫ייכלא ל‪ 15-‬שנה‪.‬‬
‫אם שני האסירים יישתקו‪,‬ייכנס כל אחד מהם לשנה בכלא‪.‬‬
‫המחלקות שעלינו לממש‬
‫• פעולה ‪Action‬‬
‫– שם הפעולה ("אבן")‬
‫• שחקן ‪Player‬‬
‫– שם השחקן (" ‪)" Andrea Farina‬‬
‫– מספר נקודות‬
‫– בחירת פעולה(מהלך) מתוך קבוצת פעולות אפשריות‪.‬‬
‫‪21‬‬
‫המחלקות שעלינו לממש‬
‫• משחק ‪Game‬‬
‫– קבוצת פעולות אפשריות("אבן‪,‬נייר‪,‬מספריים")‪.‬‬
‫– ‪ 2‬שחקנים‪.‬‬
‫– שם המשחק‪.‬‬
‫‪22‬‬
‫מימוש המחלקה של פעולה‬
public class Action {
private String name;
public Action(String n) {
name = new String(n); // name = n; will work too
}
public String getName(){
return name;
}
}
23
‫מימוש המחלקה של שחקן כללי‬
public class Player {
private String m_name;
private int m_score;
public Player(String nm){
m_name=nm;
m_score =0;
}
public Action selectAction(Action[] actions){
return actions[0];
}
public boolean isWinner(Player p){
return (m_score > p.getScore());
}
public void updateScore(int score){
m_score = m_score + score;
}
public int getScore(){
return m_score;
}
public String toString(){
return m_name;
}
?‫מה נכתוב כאן‬
}
24
‫מימוש שחקן אקראי‬
public class RandomPlayer extends Player{
public RandomPlayer(String name)
{
super(name);
}
//The selection methods – different implementation
public Action selectAction(Action[] actions)
{
return actions[(int)(Math.random()*actions.length)];
}
}
25
‫מימוש שחקן עיקבי‬
public class ConsecutivePlayer extends Player{
private int m_lastSelection;
public ConsecutivePlayer (String name)
{
super(name);
m_lastSelection = 0;
}
//The selection methods – different implementation
public Action selectAction(Action[] actions)
{
m_lastSelection = (m_lastSelection + 1)% actions.length;
return actions[m_lastSelection];
}
}
26
‫מימוש משחק כללי‬
public class Game {
private Action[] actions; // the set of actions
private Player p1, p2;
private String name; //game name
public Game (int numActions, Player p1, Player p2, String name) {
actions = new Action[numActions];
this.p1 = p1;
this.p2 = p2;
this.name = name;
}
public void addAction(int index, Action a) {
actions[index] = a;
}
public void play(int turnCount) {
for (int i=0; i<turnCount; i=i+1)
playSingleTurn();
}
private void playSingleTurn() {
/*the selection order is not important as each player does not know the choice of the other player*/
Action a1 = p1.selectAction(actions);
Action a2 = p2.selectAction(actions);
rewardPlayers(a1, a2);
}
27
)‫מימוש משחק כללי(המשך‬
public void rewardPlayers(Action a1, Action a2) {
//this is not a specific game and therefore there is no real score//
p1.updateScore(0);
p2.updateScore(0);
}
public Player getWinner () {
if (p1.isWinner(p2))
return p1;
else return p2;
}
public Player getFirstPlayer() {
return p1;
}
public Player getSecondPlayer() {
return p2;
}
public String toString() { return name; }
}
28
‫מימוש המשחק אבן נייר ומספריים‬
public class RockPaperScissors extends Game{
public RockPaperScissors(Player p1, Player p2)
{
super(3,p1,p2, "Rock Paper Scissors");
addAction(0,new Action("rock"));
addAction(1,new Action("paper"));
addAction(2,new Action("scissors"));
}
29
public void rewardPlayers(Action a1, Action a2)
{
if (a1.getName().equals(a2.getName()))
{
getFirstPlayer().updateScore(0);
getSecondPlayer().updateScore(0);
}
if ((a1. getName().equals("rock")) & (a2.getName().equals("paper")))
{
getFirstPlayer().updateScore(-1);
getSecondPlayer().updateScore(1);
}
if ((a1. getName().equals("rock")) & (a2. getName().equals("scissors")))
{
getFirstPlayer().updateScore(1);
getSecondPlayer().updateScore(-1);
}
if ((a1. getName().equals("paper")) & (a2. getName().equals("scissors")))
{
getFirstPlayer().updateScore(-1);
getSecondPlayer().updateScore(1);
}
}
}
30
‫מימוש המשחק דילמת האסיר‬
public class PrisonerDilemmas extends Game{
public PrisonerDilemmas(Player p1, Player p2)
{
super(2,p1,p2, "Prisoner's dilemma");
addAction(0,new Action("silent"));
addAction(1,new Action("blame"));
}
31
public void rewardPlayers(Action a1, Action a2)
{
if ((a1. getName().equals("blame")) & (a2. getName().equals("blame")))
{
getFirstPlayer().updateScore(-5);
getSecondPlayer().updateScore(-5);
}
if ((a1. getName().equals("silent")) & (a2. getName().equals("blame")))
{
getFirstPlayer().updateScore(-15);
getSecondPlayer().updateScore(0);
}
if ((a1. getName().equals("blame")) & (a2. getName().equals("silent")))
{
getFirstPlayer().updateScore(0);
getSecondPlayer().updateScore(-15);
}
if ((a1. getName().equals("silent")) & (a2. getName().equals("silent")))
{
getFirstPlayer().updateScore(-1);
getSecondPlayer().updateScore(-1);
}
}
}
32
‫הצורך במחלקות אבסטקטיות‬
‫היינו רוצים ליצור מחלקה‪:‬‬
‫– שתהיה מחלקת האב של כל המשחקים שתדע לעשות‬
‫את כל הדברים המשותפים‪.‬‬
‫– שתכיל הגדרה של כל השיטות המשותפות‪ ,‬כדי‬
‫שאפשר יהיה לקרוא‪ ,‬לדוגמא‪ ,‬באופן כללי‬
‫‪ rewardPlayers‬בלי לדעת מהו המשחק‪.‬‬
‫– שתשאיר מקום לכל משחק לממש את השיטות‬
‫האופייניות שלו‪.‬‬
‫– שתחייב כל משחק לממש את השיטות האופייניות שלו‪.‬‬
‫‪33‬‬
‫משחק כמחלקה אבסטרקטית‬
public abstract class Game {
protected Action[] actions;
protected Player p1, p2;
protected String name;
public Game (int numActions, Player p1, Player p2, String name) {
actions = new Action[numActions];
this.p1 = p1;
this.p2 = p2;
this.name = name;
}
public abstract void rewardPlayers(Action a1, Action a2);
34
public void addAction(int index, Action a) {
actions[index] = a;
}
public void play(int turnCount) {
for (int i=0; i<turnCount; i=i+1)
playSingleTurn();
}
private void playSingleTurn() {
Action a1 = p1.selectAction(actions);
Action a2 = p2.selectAction(actions);
rewardPlayers(a1, a2);
}
public Player getWinner () {
if (p1.isWinner(p2))
return p1;
else return p2;
}
public Player getFirstPlayer() {
return p1;
}
public Player getSecondPlayer() {
return p2;
}
public String toString() { return name; }
}
35
‫מחלקות אבסטרקטיות‬
‫{>‪public abstract class <name‬‬
‫;) ‪public abstract void <method name> ( ...‬‬
‫…‬
‫}‬
‫• במחלקה אבסטרקטית יכולות להיות פונקציות‬
‫רגילות‪ ,‬כמו בכל מחלקה‪.‬‬
‫• בנוסף יכולות להיות לה פונקציות אבסטרקטיות‪:‬‬
‫פונקציות שההגדרה שלהן קיימת אבל אין להן‬
‫מימוש‪.‬‬
‫• אנו מכריזים על מחלקה או על שיטה‬
‫כאבסטרקטית בעזרת המילה השמורה ‪.abstract‬‬
‫‪36‬‬
‫מחלקות אבסטקטיות(המשך)‬
‫• בגלל שמחלקה אבסטרקטית מכילה שיטות שאינן‬
‫מוגדרות (שיטות אבסטרקטיות) לא ניתן ליצור‬
‫ממנה מופעים‪.‬‬
‫– ;)(‪Game g = new Game‬‬
‫שגיאת קומפילציה‬
‫• מחלקה שמרחיבה מחלקה אבסטרקטית ולא‬
‫מממשת את כל השיטות האבסטרקטיות‪ ,‬חייבת‬
‫להיות אבסטרקטית בעצמה‪.‬‬
‫‪37‬‬
‫מחלקות אבסטקטיות(המשך)‬
‫• מחלקה יכולה להיות אבסטרקטית‪ ,‬גם אם אין לה‬
‫פונקציות אבסטרקטיות‪ .‬בצורה זו אנו מונעים‬
‫מהמשתמש ליצור ממנה מופע‪.‬‬
‫‪38‬‬
‫מימוש המשחק דילמת האסיר‬
‫ אבסטקטית ועל כן אנו חייבים‬Game ‫• המחלקה‬
.rewardPlayers ‫לממש את השיטה‬
.‫• זהה לחלוטין למימוש שהצגנו קודם‬
public class PrisonerDilemmas extends Game{
public PrisonerDilemmas(Player p1, Player p2)
{
super(2,p1,p2, "Prisoner's dilemma");
addAction(0,new Action("silent"));
addAction(1,new Action("blame"));
}
39
public void rewardPlayers(Action a1, Action a2)
{
if ((a1. getName().equals("blame")) & (a2. getName().equals("blame")))
{
getFirstPlayer().updateScore(-5);
getSecondPlayer().updateScore(-5);
}
if ((a1. getName().equals("silent")) & (a2. getName().equals("blame")))
{
getFirstPlayer().updateScore(-15);
getSecondPlayer().updateScore(0);
}
if ((a1. getName().equals("blame")) & (a2. getName().equals("silent")))
{
getFirstPlayer().updateScore(0);
getSecondPlayer().updateScore(-15);
}
if ((a1. getName().equals("silent")) & (a2. getName().equals("silent")))
{
getFirstPlayer().updateScore(-1);
getSecondPlayer().updateScore(-1);
}
}
}
40
‫שחקן כמחלקה אבסטרקטית‬
public abstract class Player {
private String m_name;
private int m_score;
public Player(String nm)
{
m_name=nm;
m_score =0;
}
public abstract Action selectAction(Action[] actions);
41
‫מחלקות אבסטרקטיות‬
‫ממשקים‬
‫לא ניתן ליצור מופעים‬
‫לא ניתן ליצור מופעים‬
‫שימוש במחלקה אבסטרקטית ע"י ירושה‬
‫‪extends‬‬
‫שימוש בממשק מתבצע ע"י מימושו‬
‫‪implements‬‬
‫מחלקה אבסטרקטית יכולה להכיל קוד של‬
‫חלק מהשיטות‬
‫הממשק הינו רשימה של שיטות ללא כל‬
‫מימוש‬
‫יורשי מחלקה זו יהיו בעלי יישומים דומים‬
‫(הקוד המשותף) וכן בעלי יישומים שונים‬
‫(השיטות האבסטרקטיות)‬
‫ממשק הוא רעיון מופשט אשר ליורשיו אין אף‬
‫יישום משותף‪.‬‬
‫מחלקה יכולה לרשת מחלקה אבסטרקטית‬
‫אחת בלבד‬
‫מחלקה יכולה לממש מספר ממשקים‬
‫אין הגבלה על המשתנים‬
‫כל משתנה חייב להיות‬
‫‪static final‬‬
‫‪42‬‬