What is an Interface An interface is a

  • Slides: 32
Download presentation
What is an Interface? ? An interface is a ‘container’ which contains ONLY abstract

What is an Interface? ? An interface is a ‘container’ which contains ONLY abstract methods. public interface Capitalizable { public abstract String out. Caps() ; //returns String representation of object in all capital letters public abstract String out. First. Cap(); //returns String representation of object w/ first char in caps public abstract String out. No. Caps(); // returns String representation of object in all lowercase }

What is an Interface FOR? ? An interface can be used to FORCE a

What is an Interface FOR? ? An interface can be used to FORCE a class to provide certain functionality. Suppose we needed to be certain that the class Sentence provided a way to output the object data: • • • in all capitals with first letter capitalized in all lower case

public class Sentence implements Capitalizable { String the_data; public Sentence() { // code for

public class Sentence implements Capitalizable { String the_data; public Sentence() { // code for this method } public void add. Word(String word) { // code for this method } public int how. Many() { // code for this method }

//the class will not compile without these methods!! public String out. Caps() { //

//the class will not compile without these methods!! public String out. Caps() { // code for this method } public String out. First. Cap(){ // code for this method } public String out. No. Caps() { // code for this method } ADDITIONALLY, an object of class Sentence is ALSO an object of type Capitalizable!!!!!!

Why might I need to ensure that Sentence offers these methods? ? Suppose we

Why might I need to ensure that Sentence offers these methods? ? Suppose we wanted to write a program which stored 15 Sentence objects, output them in capital letters, and output the first capital letter in each Sentence;

//Since Sentence implements the Capitalizable interface, Sentence is of type Capitalizable (and has the

//Since Sentence implements the Capitalizable interface, Sentence is of type Capitalizable (and has the needed method). If Sentence didn’t implement the Capitalizable interface, this program wouldn’t compile. public static main (String[] args) { Capitalizable [] sobj; sobj = new Capitalizable [16]; // sobj stores Capitalizable references sobj[0] = new Sentence(); // so we can assign a Sentence object! …. . // the other assignments sobj[15] = new Sentence(); for (int index=0; index < 16; index++) System. out. println( “Object at index “ + index + “ is “ + sobj[index]. out. Caps() ); //the author of this method KNOWS that the out. Caps method is there }

Suppose we KNEW that the Sentence class, the Paragraph class, the Word class and

Suppose we KNEW that the Sentence class, the Paragraph class, the Word class and the Block. Text implemented the Capitalizable interface!! and we wanted to write a program which stored, and manipulated 15 Sentence objects, 15 Paragraph objects, 15 Word object, and 15 Block. Text objects

Capitalizable [] textobj; textobj = new Capitalizable [60]; textobj[0] = new Sentence(); textobj[1] =

Capitalizable [] textobj; textobj = new Capitalizable [60]; textobj[0] = new Sentence(); textobj[1] = new Paragraph(); textobj[2] = new Word(); textobj[3] = new Block. Text(); …. . // other assignments textobj[59] = new Block. Text(); // this array can store varying types of objects // all objects can be output in capitals using the same code – // because it is KNOWN that each object has an out. Caps method for (int index=0; index < 16; index++) System. out. println( “Object at index “ + index + “ is “ + textobj[index]. out. Caps() );

You have already seen an interface…. Shape * The Shape interface provides a number

You have already seen an interface…. Shape * The Shape interface provides a number of abstract methods, just like any other interface. * Rectangle 2 D, Line 2 D, Ellipse 2 D, Round. Rectangle 2 D, Rectangle 2 D all implement (realize) the Shape interface. * So a object created from any of these classes is an object of type Shape. * An array declared and instantiated as: Shape [ ] shapelist = new Shape[40]; is capable of storing 40 objects instantiated from any of these classes.

For example: import ……. public class My. Shapes extends JComponent{ private Shape [ ]

For example: import ……. public class My. Shapes extends JComponent{ private Shape [ ] shapelist = new Shape[4]; public My. Shapes() { //create the draw shapelist[0] = new Rectangle 2 D. Double(x, y, width, height); shapelist[1] = new Ellipse 2 D. Double(x, y, width, height); shapelist[2] = new Line 2 D. Double(x, y, width, height); shapelist[3] = new Round. Rectangle 2 D. Double(x, y, width, height); }

My. Shapes class continued…. public void paint. Component(Graphics g) { Graphics 2 D g

My. Shapes class continued…. public void paint. Component(Graphics g) { Graphics 2 D g 2 = (Graphics 2 D) g; // draw all the shapes for (int index = 0; index < 4; index ++ ) g 2. draw(shapelist[index]); }

The My. Shapes class does not make use of the fact that all the

The My. Shapes class does not make use of the fact that all the objects in the array have many method names in common. This component only uses their common type to allow one array to be used to the all the shapes. ------------------------------BUT, since the Shape interface is common to the Line 2 D. Double class, Rectangle 2 D. Double class and many other classes, any object that is created from one of these classes is known to provide a common set of methods. We can look at the JAVA API documentation to see what these methods are. The Graphics 2 D method draw(Shape) knows what these methods are, and uses them -- which is why the parameter must be a Shape.

another use of interfaces … Suppose we had a class named Bank. Accounts, where

another use of interfaces … Suppose we had a class named Bank. Accounts, where an object of this class represented one bank account. (one method of this class is get. Balance, which gives the account balance). Now we want to create a class named BAData. Set, which can monitor a group Bank. Account objects, and keep track of: 1. ) total of all bank account balances 2. ) largest balance

BAData. Set might look like this: public class BAData. Set private double sum; {

BAData. Set might look like this: public class BAData. Set private double sum; { //total of all account balances private Bank. Account maximum; //account w/ highest balance private int count; //number of accounts in set public void add ( Bank. Account x ){ sum = sum + x. get. Balance(); if (count == 0 || maximum. get. Balance()< x. get. Balance()) maximum = x; } count++; public Bank. Account get. Maximum(){ return maximum; }

Suppose we had a class named Coin, where an object of this class represents

Suppose we had a class named Coin, where an object of this class represents one coin. (one method of this class is get. Total, which gives the value of the coin). Now we want to create a class named CData. Set, which can keeps track of a number of Coin objects, keeping track of the total cash and largest coin in a collection of coins.

CData. Set might look like this: public class CData. Set { private double sum;

CData. Set might look like this: public class CData. Set { private double sum; //total of all coin objects private Coin maximum; //coin object with highest value private int count; //number of coin objects in set public void sum = sum if (count maximum count++; } add (Coin x) { + x. get. Total(); == 0 || maximum. get. Total()< x. get. Total()) = x; public Coin get. Maximum(){ return maximum; }

Gee, both of those classes look quite alike. In fact, except for: * method

Gee, both of those classes look quite alike. In fact, except for: * method calls: get. Balance(). vs. get. Total() * parameter/return types it is the same code. How can we write ONE Data. Set class which can handle both types of objects? ?

 • Suppose both classes could agree on the same method name, say, get.

• Suppose both classes could agree on the same method name, say, get. Measure • Data. Set could call that method: sum = sum + x. get. Measure(); if (count == 0 || maximum. get. Measure() < x. get. Measure()) maximum = x; • Define an interface: public interface Measurable { public abstract double get. Measure(); }

Remember …. • when a class ‘implements’ an interface it must provide a full

Remember …. • when a class ‘implements’ an interface it must provide a full implementation of the abstract methods in the interface • So, if both Bank. Account and Coin classes ‘implemented’ the measurable interface, we know they have the method get. Measure

class Bank. Account implements Measurable{ double balance; //additional variables and methods public double get.

class Bank. Account implements Measurable{ double balance; //additional variables and methods public double get. Measure(){ return balance; } } class Coin implements Measurable{ double value; //additional variables and methods public double get. Measure(){ return value; } }

public class Data. Set { private double sum; private ***** maximum; private int count;

public class Data. Set { private double sum; private ***** maximum; private int count; public void add(***** x){ sum = sum + x. get. Measure(); if (count == 0 || maximum. get. Measure() < x. get. Measure()) maximum = x; count++; } public ****** get. Maximum(){ return maximum; } WE have taken care of the method name, but what data type will work, can’t be Bank. Account and can’t be Coin!! }

Remember …. • when a class ‘implements’ an interface, objects of that class ARE

Remember …. • when a class ‘implements’ an interface, objects of that class ARE objects of the interface type as well Eg. A Bank. Account object is ALSO a Measurable object • So, if both Bank. Account and Coin classes ‘implemented’ the Measurable interface, we know they are both objects of class Measurable !

public class Data. Set { private double sum; private Measurable maximum; private int count;

public class Data. Set { private double sum; private Measurable maximum; private int count; public void add(Measureable x){ sum = sum + x. get. Measure(); if (count == 0 || maximum. get. Measure() < x. get. Measure()) maximum = x; count++; } public Measurable get. Maximum(){ return maximum; } }

// This program tests the Data. Set class. public class Data. Set. Test{ public

// This program tests the Data. Set class. public class Data. Set. Test{ public static void main(String[] args) { Data. Set bank. Data = new Data. Set(); bank. Data. add(new Bank. Account(0)); bank. Data. add(new Bank. Account(10000)); bank. Data. add(new Bank. Account(2000)); System. out. println("Average balance = " + bank. Data. get. Average()); Measurable max = bank. Data. get. Maximum(); System. out. println("Highest balance = " + max. get. Measure());

Data. Set coin. Data = new Data. Set(); coin. Data. add(new Coin(0. 25, "quarter"));

Data. Set coin. Data = new Data. Set(); coin. Data. add(new Coin(0. 25, "quarter")); coin. Data. add(new Coin(0. 1, "dime")); coin. Data. add(new Coin(0. 05, "nickel")); System. out. println("Average coin value = " + coin. Data. get. Average()); max = coin. Data. get. Maximum(); System. out. println("Highest coin value = " + max. get. Measure()); } }

UML Diagram Note that Data. Set is decoupled from Bank. Account, Coin

UML Diagram Note that Data. Set is decoupled from Bank. Account, Coin

Converting Between Types • Can convert from class type to realized interface type: Bank.

Converting Between Types • Can convert from class type to realized interface type: Bank. Account account = new Bank. Account(10000); Measurable x = account; // OK • Same interface type variable can hold reference to Coin x = new Coin(0. 1, "dime"); // OK • Cannot convert between unrelated types x = new Rectangle(5, 10, 20, 30); // ERROR

Casts • Add coin objects to Data. Set coin. Data = new Data. Set();

Casts • Add coin objects to Data. Set coin. Data = new Data. Set(); coin. Data. add(new Coin(0. 25, "quarter")); coin. Data. add(new Coin(0. 1, "dime")); . . . • Get largest coin with get. Maximum method: Measurable max = coin. Data. get. Maximum(); If the coin class also has a method called ‘get. Name’ which returns the type of coin as a String…… • You know it's a coin, but the compiler doesn't. Apply a cast: Coin max. Coin = (Coin)max; String name = max. Coin. get. Name(); • If you are wrong and max isn't a coin, the compiler throws an exception

The instanceof Operator • Use instanceof for safe casts: if (max instanceof Coin) {

The instanceof Operator • Use instanceof for safe casts: if (max instanceof Coin) { Coin max. Coin = (Coin)max; . . . }

object instanceof Class. Name Example: if (x instanceof Coin) { Coin c = (Coin)x;

object instanceof Class. Name Example: if (x instanceof Coin) { Coin c = (Coin)x; } Purpose: To return true if the object is an instance of Class. Name (or one of its subclasses), false otherwise

Polymorphism • Interface variable x holds reference to object of a class that realizes

Polymorphism • Interface variable x holds reference to object of a class that realizes (implements) the interface Measurable x; x = new Bank. Account(10000); x = new Coin(0. 1, "dime"); • You can call any of the interface methods: double m = x. get. Measure(); • Which method is called?

 • Which method is called? Depends on the actual object. If x refers

• Which method is called? Depends on the actual object. If x refers to a bank account, calls Bank. Account. get. Measure If x refers to a coin, calls Coin. get. Measure Java can handle this because it supports polymorphism (greek: many shapes) => one reference can refer to different types of objects In the case of a polymorphic object, the actual method which will be called is determined by the type of the object. How does this work? ? The JVM uses the actual type of object to determine method to execute at runtime !! (dynamic or late binding) This is called polymorphism. *Different from overloading. Overloading is resolved by the compiler (at compile time).