public class Employee private String name private Date
public class Employee { private String name; private Date hire. Date; public String to. String(){ return (name + " " + hire. Date. to. String( )); } } public class Hourly. Employee extends Employee { private double wage. Rate; private double hours; //for the month public String to. String( ){ return (super. to. String ( ) + "n$" + wage. Rate + " per hour for " + hours + " hours "); } } public class Salaried. Employee extends Employee { private double salary; //annual public String to. String( ){ return (super. to. String( ) + "n$" + salary + " per year"); } }
public class Is. ADemo { public static void main(String[] args) { Salaried. Employee sam = new Salaried. Employee("Josephine", new Date("January", 1, 2004), 100000); Hourly. Employee han = new Hourly. Employee("Sam", new Date("February", 1, 2003), 50. 50, 40); System. out. println("show. Employee(sam) invoked: "); show. Employee(sam); System. out. println("show. Employee(han) invoked: "); show. Employee(han); } public static void show. Employee(Employee employee. Object) { System. out. println(employee. Object. to. String()); } } Τι θα τυπώσει η show. Employee όταν την καλέσουμε με ορίσματα το sam και το han? Ποια μέθοδος to. String θα κληθεί?
public class Is. ADemo { public static void main(String[] args) { Salaried. Employee sam = new Salaried. Employee("Josephine", new Date("January", 1, 2004), 100000); Hourly. Employee han = new Hourly. Employee("Sam", new Date("February", 1, 2003), 50. 50, 40); System. out. println("show. Employee(sam) invoked: "); show. Employee(sam); System. out. println("show. Employee(han) invoked: "); show. Employee(han); } public static void show. Employee(Employee employee. Object) { System. out. println(employee. Object. to. String()); } } Θα καλέσει την to. String της κλάσης του αντικειμένου περνάμε σαν όρισμα (Hourly. Employee ή Salaried. Employee) και όχι την κλάση που εμφανίζεται στον ορισμό της παραμέτρου (Employee). Ο μηχανισμός αυτός ονομάζεται late binding (και/ή πολυμορφισμός)
Παράδειγμα public class Example 3 { public static void main(String[] args) { Employee employee. Array[] = new Employee[3]; employee. Array[0] = new Employee("alice", new Date(1, 1, 2010)); employee. Array[1] = new Hourly. Employee("bob", new Date(1, 1, 2011), 20, 160); employee. Array[2] = new Salaried. Employee("charlie", new Date(1, 1, 2012), 24000); for (int i = 0; i < 3; i ++){ System. out. println(employee. Array[i]); } } } Για κάθε στοιχείο του πίνακα καλείται διαφορετική μέθοδος to. String ανάλογα με το αντικείμενο που τοποθετήσαμε σε εκείνη τη θέση
public class Sale { protected String name; protected double price; Σύμφωνα με το βιβλίο δεν συνίσταται η χρήση της protected αλλά την χρησιμοποιούμε για απλότητα στο παράδειγμα public Sale(String the. Name, double the. Price){ name = the. Name; price = the. Price; } public String to. String( ){ return (name + " Price and total cost = $" + price); } public double bill( ){ return price; } public boolean equal. Deals(Sale other. Sale){ return (name. equals(other. Sale. name) && this. bill( ) == other. Sale. bill( )); } public boolean less. Than (Sale other. Sale){ return (this. bill( ) < other. Sale. bill( )); } }
public class Discount. Sale extends Sale { private double discount; public Discount. Sale(String the. Name, double the. Price, double the. Discount) { super(the. Name, the. Price); discount = the. Discount; } public double bill( ) { double fraction = discount/100; return (1 - fraction)*price; } Υπέρβαση της μεθόδου bill() public String to. String( ) { return (name + " Price = $" + price + " Discount = " + discount + "%n" + " Total cost = $" + bill( )); } } Δεν έχουμε υπέρβαση των μεθόδων equal. Deals και less. Than
public class Late. Binding. Demo { public static void main(String[] args) { Sale simple = new Sale("floor mat", 10. 00); //One item at $10. 00. Discount. Sale discount = new Discount. Sale("floor mat", 11. 00, 10); //One item at $11. 00 with a 10% discount. System. out. println(simple); System. out. println(discount); Οι less. Than και equal. Deals κληρονομούνται από την Sale if (discount. less. Than(simple)) System. out. println("Discounted item is cheaper. "); else System. out. println("Discounted item is not cheaper. "); Sale regular. Price = new Sale("cup holder", 9. 90); //One item at $9. 90. Discount. Sale special. Price = new Discount. Sale("cup holder", 11. 00, 10); //One item at $11. 00 with a 10% discount. System. out. println(regular. Price); System. out. println(special. Price); Με το μηχανισμό του late binding στην κλήση τους ξέρουμε ότι το αντικείμενο που τις καλεί είναι τύπου Discount. Sale if (special. Price. equal. Deals(regular. Price)) System. out. println("Deals are equal. "); else System. out. println("Deals are not equal. "); } } Ξέρουμε λοιπόν ότι όταν εκτελούμε τον κώδικα της less. Than και equal. Deals η μέθοδος bill() που θα πρέπει να καλέσουμε είναι αυτή της Discount. Sale ενώ για το other. Sale. bill() είναι αυτή της Sale
Ορισμός της αφηρημένης κλάσης public abstract class Employee { private String name; private Date hire. Date; Ορισμός της αφηρημένης μεθόδου public abstract int get. Pay(); public boolean same. Pay(Employee other){ return (this. get. Pay() == other. get. Pay()); } Χρήση της αφηρημένης μεθόδου και της αφηρημένης κλάσης public Employee( ) { … } public Employee(String the. Name, Date the. Date) { … } public Employee(Employee original. Object) { … } public String get. Name( ) { … } public void set. Name(String new. Name) { … } public Date get. Hire. Date( ) { … } public void set. Hire. Date(Date new. Date) { … } Όταν καλέσουμε την same. Pay θα την καλέσουμε με ένα αντικείμενο μιας από τις παράγωγες κλάσεις. public String to. String() { … } }
public class Hourly. Employee extends Employee { private double wage. Rate; private double hours; //for the month public Hourly. Employee( ) { … } public Hourly. Employee(String the. Name, Date the. Date, double the. Wage. Rate, double the. Hours) { … } public Hourly. Employee(Hourly. Employee original. Object) { … } public double get. Rate( ) { … } public void set. Rate(double new. Wage. Rate) { … } public double get. Hours( ) { … } public void set. Hours(double hours. Worked) { … } public double get. Pay( ) { return wage. Rate*hours; } public String to. String( ){ … } } Εφόσον η κλάση Hourly. Employee παράγεται από αφηρημένη κλάση και η ίδια δεν είναι αφηρημένη, πρέπει υποχρεωτικά να ορίσει την αφηρημένη μέθοδο get. Pay
public class Salaried. Employee extends Employee { private double salary; //annual public Salaried. Employee( ) { … } public Salaried. Employee(String the. Name, Date the. Date, double the. Salary) { … } public Salaried. Employee(Salaried. Employee original. Object ) { … } public double get. Salary( ) { … } public void set. Salary(double new. Salary) { … } public double get. Pay( ) { return salary/12; } public String to. String( ) { … } } Εφόσον η κλάση Salaried. Employee παράγεται από αφηρημένη κλάση και η ίδια δεν είναι αφηρημένη, πρέπει υποχρεωτικά να ορίσει την αφηρημένη μέθοδο get. Pay
public class Example { public static void main(String args[]){ Hourly. Employee A = new Hourly. Employee(“Alice", new Date(4, 18, 2013), 100); Salaried. Employee B = new Salaried. Employee(“Bob", new Date(4, 17, 2013), 12000); if (A. same. Pay(B)){ System. out. println("The two employees take the same amount per month"); } else{ System. out. println("The two employees do NOT take the same amount per month"); } } }
Παραδείγματα public interface Moving. Object { public void move(); } public interface Electric. Object { public boolean power. On(); public boolean power. Off(); }
Παραδείγματα public class Car implements Moving. Object { … } public class Electric. Car implements Moving. Object, Electric. Object { … } public abstract class Vehicle implements Moving. Object { public abstract void move(); } public class Electric. Car extends Vehicle, implements Electric. Object { … }
Interfaces • Ένα Interface μπορεί να κληρονομεί από ένα άλλο interface public interface Electric. Moving. Object extends Moving. Object { public boolean power. On(); public boolean power. Off(); }
Interface my. Comparable public interface my. Comparable { public int compare. To(my. Comparable other); }
import java. util. Scanner; class Person implements my. Comparable { private String name; private int number; public Person(){ System. out. println("enter name and number: "); Scanner input = new Scanner(System. in); name = input. next(); number = input. next. Int(); } public String to. String(){ return name + " " + number; } public int compare. To(my. Comparable other){ Person other. Person = (Person) other; if (number < other. Person. number){ return -1; }else if (number == other. Person. number){ return 0; } else { return 1; } } } Χρήση του Down. Casting
public class Comparable. Example { public static void main(String[] args){ Person[] array = new Person[5]; for (int i = 0; i < array. length; i ++){ array[i] = new Person(); } sort(array); System. out. println(); for (int i = 0; i < array. length; i ++){ System. out. println(array[i]); } } public static void sort(my. Comparable[] array){ for (int i = 0; i < array. length; i ++){ my. Comparable min. Element = array[i]; for (int j = i+1; j < array. length; j ++){ if (min. Element. compare. To(array[j]) > 0){ min. Element = array[j]; array[j] = array[i]; array[i] = min. Element; } } }
- Slides: 31