Interfaces

advertisement
Java 211 – Lecture IX
Interfaces
Yosef Mendelsohn
An aside: More practice with arrays…. LetterCount.java
The Die class used with an applet…. Die.java, DiceApplet.java
Packages
A package is a group of classes grouped together under a name.
- All of the standard classes in Java are contained within packages. For example,
the classes Math, String, and System are all contained in a package called
“java.lang”
One of the benefits of Java is the tremendous number of classes written by third party
groups, (By ‘third-party’ we mean groups not necessarily affiliated with Sun, the
creators of Java). Even the String class is not a de-facto part of the Java standard.
However, its use is so obviously necessary for the development of even rudimentary
programs, that this class gets shipped along with all standard implementations of Java.
There are several similarly useful classes that you will automatically receive when you
download the SDK. These classes make up the Java standard class library. The
functionality provided by these libraries include mathamatical capabilities, networking
capabilities, security functionality, applets, graphics, and others.
A group of related classes is usually bundled into a package. Some packages in the Java
standard class library include: java.applet, java.awt, java.math, java.lang,
java.security, java.sql
In order to use a class, we must first import it into our program. For example, to use the
String class, we would need to import it from the java.lang package:
import java.lang.String;
Similarly, if we wanted to use the System class, we would import it using:
import java.lang.System;
Alternatively, we could import all of the classes in java.lang by issuing:
import java.lang.*;
As we’ve just discussed, the String class is part of the java.lang package. So is the
‘System’ class. However, notice that we did not have to use the ‘import’ statement
discussed in the previous paragraphs. The reason is that since these classes are used so
frequently, the ‘java.lang’ package is automatically included for us in every Java
program. It is as if the line:
import java.lang.*;
is invisible, but present in every program.
The ‘*’ after java.lang says to import all classes from the library (package). If we only
wanted to use, say, the String class, we could instead type:
import java.lang.String;
But again, this is a moot point since as we said, the entire java.lang package is imported
into every Java program.
Let’s take a look at some other useful classes:
See:
- RandomNumbers.java (API Specification for Random class)
- Price.java
- CircleStats.java //makes use of the Loftus textbook’s keyboard class…
Notice how in the CircleStats.java program there is an import statement that says:
‘import cs1.Keyboard;” . The problem here is that this package is not part of the
Java standard library. Since we are making use of a non-standard library, we must have a
copy of this package to put somewhere, where our compiler can make use of it.
- This directory makes up the package. That is, to create a package, you simply
take a number of related classes, and put them in a directory of whatever name
you choose. The name you give to your directory becomes the name of the
package.
Static Methods: Invoking Without Instantiating
Typically, to access a field or invoke a method, we need to specify an object. However,
there is one exception: ‘static’ fields or methods. A method or field that is static can be
accessed without requiring a calling object.
Recall that whenever we specify a member variable (field) or a method of a class, we
must specify an object to invoke the method (or on which to alter a field). For example, I
can’t simply call the ‘toUpperCase()’ method of the String class without specifying a
String object. However, there are some methods which can be invoked without
specifying an object. These are called ‘static’ methods.
For example, the Math class has a method called Random() (very similar to the Random
class we saw in the java.util package). As discussed earlier, it is not uncommon in
programming to want to get a random number from the program. If this method was not
a static method, I would have to do the following:
Math num = new Math();
double n = num.random();
By the way, the line Math num = new Math(); is not even allowed in Java. It is
not possible to instantiate objects of type Math. (The explanation of why is beyond the
scope of this lecture).
In other words, we had to create a Math object for no other reason than to generate the
random number we wish to put into ‘n’. We have no plans to use this object again. For
this reason, the developers of the class made ‘random’ a static method. This means that
you do NOT need an object to invoke the method. Simply providing the name of the
class is sufficient:
double n = Math.random();
In fact, in the example earlier, the statement Math num = new Math(); is illegal
since you cannot instantiate a static class.
This is the same thing we saw with the textbook’s Keyboard class earlier. To invoke any
of the methods such as ‘readInt()’, ‘readString()’ etc, we need only specify the class
name: String s = Keyboard.readString();
Look at the header for this method:
static String readString() { …
- See Echo.java
Assignment: A big part of learning Java is learning how to make use of the many classes
available to you. Take a look at and experiment with the DecimalFormat class that we
made use of in the CircleStats.java program earlier. Try to find the API of the class from
the link provided here. You can do a search in the ‘All Classes’ frame (lower right).
More on the ‘static’ modifier
Recall that if a method is declared static, this means that we can invoke the method
without even having to have an instantiation of the class. Ordinarily to invoke a method,
we must first specify an object. However, with a static method, we do not need to
instantiate, and can invoke by simply qualifying the method name with the class (not
object) name.
System.out.println(“The square root of 27 is: “ +
Math.sqrt(27) );
Here, the sqrt() method of the class Math is a static method. Therefore we can invoke it
by simply providing the class name. In fact, all methods of the Math class are static.
Note how we have always created main() with a static modifier. This is so that main()can
be instantiated by the interpreter without having to instantiate an object from whatever
class contains main().
Static Variables
We’ve already discussed the ‘scope’ of variables. For example, a variable defined inside
a method is “local” to that method. That is, the variable does not exist outside of that
method. If you attempt to refer to variable outside of its scope, the compiler will give
you an error.
We’ve also seen variables that are tied to a class. For example, the StudentRecord class
we discussed earlier in the quarter has a number of “instance variables” (fields)
including: lastName, firstName, totalHwGrade, etc. These are called instance variables
since the only way you can refer to them is via an instance (object) of the class. This
makes sense, since, for example, the ‘lastName’ field only makes sense in the context of
a StudentRecord object. For instance variables, each object of the class reserves memory
for its own copy of that variable.
However, there are times when you might want a variable to belong to all objects of the
class. That is, you might want the variable to have the same value for all objects of the
class. In this case, each object of the class shares the same memory space for the
variable. If any one object changes the value of the variable, the value is changed for all
objects of that class. These are called static variables. In the StudentRecord class, there
is one such variable, ‘section’ that stores the section number for that class. All objects of
type StudentRecord will have the same value for ‘section’.
Question: Can you remember what the ‘final’ modifier stands for?
Memory space for a static variable is reserved the first time the class is referenced by the
program. (E.g. The first time the class is instantiated).
Note that static methods can not refer to non-static variables. This is because non-static
variables only exist in the context of an object. However, static methods do not exist in
the context of an object, and therefore, know nothing about non-static (“instance”)
variables. Static methods can, of course, access static variables.
See CountInstances.java , and MyClass.java .
‘this’ Reference
‘this’ is a reserved word in Java. It is used when an object needs to refer to itself. For
example, if you are inside a method and you need to refer to the calling object (the object
that invoked the method), you can refer to that object by using the keyword ‘this’. We
will discuss ‘this’ further as we progress.
public boolean move(ChessPiece cp) {
if (this.position == cp.position)
// ‘this’ refers to the calling object
return false;
… more code…
}
Interfaces
An interface is not a class, although it looks very similar. The formal definition for a
Java interface is: “a collection of constants and abstract methods’. You are already
familiar with the concept of a constant. An abstract method is simply a method without
any definition. (I.e. An empty method).
To declare an interface:
public interface Speaker {
public void method1(String s);
public void method2();
}
-
Note the use of the word ‘interface’ instead of the word ‘class’.
Note how the methods are not followed by implementation.
Abstract Methods
An abstract method is declared by giving the header of the method (i.e. visibility
modifiers, method name, formal parameters), and following it by a semicolon (i.e. no
braces).
- By default, abstract methods have public visibility.
- Abstract methods can be preceded by the word ‘abstract’, though within
interfaces, they typically are not.
Implementing an interface class
To use an interface, the interface must be implemented. To implement an interface, a
class must provide implementations for all of the methods listed in the interface. A class
that implements an interface uses the reserved word ‘implements’.
public class SomeClass implements SomeInterface { …
Note: Implementing is not the same as extending. When you extend a class (as you have
seen done with applets), you are using a technique called ‘Inheritance’. Implementing an
interface is something different although there are a few similarities.
Again, remember that the compiler will display errors if an implementation class fails to
provide definitions for all of the methods in the interface.
See: Speaker.java and Philosopher.java
- The Speaker class (an interface), has only two methods.
- The Philosopher class implements both methods listed in the Speaker interface.
Those methods are defined with the same signatures (i.e. method names, and
number and types of formal parameters) as the methods provided in the interface.
- In addition, the Philosopher class has methods of its own.
So when a class implements an interface, it “promises” that it will provide
implementations for all of the methods listed in the interface. (However, this does not
restrict the class from also adding other new methods on its own).
-
Multiple classes can implement the same interface. For example, the class
Dog.java also implements the Speaker interface.
A class can implement multiple interfaces at the same time. All it has to do is
provide implementations for all of the methods contained in those interfaces.
public class SomeClass implements Interface1,
Interface2, Interface3 { ...
All Philosopher objects can ‘speak’ and ‘announce’ since they are Speaker objects. (That
is, Philosopher objects have these methods defined). Dog objects too are Speaker
objects, and therefore can ‘speak’ and ‘announce’. Philosopher objects can also
‘pontificate’, though Dog objects cannot.
In other words:
All Dogs are Speakers
All Philosophers are Speakers
Speakers, however, are neither Philosophers, nor Dogs.
Constants
Recall that we defined an interface as being a collection of constants and abstract
methods. So, we know that an interface may contain constants. When a class
implements an interface, it gains access to all of the constants defined in the interface.
This is a convenient way for multiple classes to share a group of constants.
The Interface construct provides the basis for an important programming technique called
polymorphism.
Polymorphism (by using Interfaces)
The term ‘polymorphism’ means “to have many forms”. A polymorphic reference is a
reference that can refer to different types of objects. Interfaces are one way of allowing
us to use polymorphism. Consider:
Speaker s;
//s is a reference to a Speaker
s = new Dog();
//s is a reference to a Dog object
s.speak();
//invokes the ‘speak’ method of the Dog class
s = new Philosopher();
//s is a reference to a Philosopher
s.speak();
//invokes the ‘speak’ method of the Philosopher class
So at different times, the same reference ‘s’ can refer to completely different types of
objects. Therefore, ‘s’ is a polymorphic reference.
Notice how looking at the statement: s.speak(); in isolation does not allow us to
determine which method of speak() will be invoked. An important yet subtle rule is
illustrated here: It is the type of object rather than the type of reference that determines
which method gets invoked.
See: Talking.java
Casting References
At the end of Talking.java notice the statement:
((Philosopher) current).pontificate();
What we have had to do here is cast the reference ‘current’ to a Philosopher prior to
invoking the pontificate() method. The reason we cannot simply invoke pontificate()
directly is that ‘current’ is a reference to a Speaker. We can only invoke methods that are
guaranteed to exist for the calling reference. (“calling reference” = the reference that
invoked the method). If we wish to invoke other methods that are not guaranteed to exist,
we must cast ‘current’ to the datatype which contains the method we wish to invoke.
While this may seem to contradict the principle that it is the object that determines which
method gets invoked, it does not. It is true that it is the object that determines which
method gets invoked. However, for a reference to attempt to invoke a method, the
method must first be guaranteed to exist. Since the method pontificate() is not guaranteed
to exist for all Speaker objects, we must first cast ‘current’ to a reference where the
method is guaranteed to exist.
Download