/* Interfaces and Inheritance in Java Basic Notes In computer programming we often distinguish between *implementation* and *specification*. A specification is a set of minimal requirements for a program. Implementation is code that executes some algorithm. A single specification can have multiple implementations. Syntactically, when I write a function int f(int x) { return x+1; } The specification is int f(int x) and the code inside {}'s is the implementation. A specification can also be written formally as an *interface* in java. When you write a class in Java, it can *extend* another class (but only one) and *implement* one or more interfaces. Extending a class allows the "subclass" to inherit all definitions from the "superclass". Furthermore, all definitions in the superclass not marked "private" are visible in the subclass. In addition, the subclass may override definitions in the superclass. An interface, however, normally only contains the "header" or "signature" of methods. It may not contain full function implementations or declarations of variables (there are some exceptions, but we won't use them for now). The header of a method/function is the just the first line of a method that names the method and declares its parameters and return types. When you say that a class implements an interface, you are making a *promise* to provide full definitions of the methods named in the interface. If your class does not provide full definitions of all methods named in an interface, you will get a compiler error. So remember, "extends" adds ability to your class by inheriting definitions from a superclass. "implements" is just a promise that your class will provide implementations of certain functions, i.e., that it will *satisfy a specification*. */ interface I // sample interface { int f(); void g(); int h(); // int x; // not legal in interface (unless static final) // int h() { return 2; } // not legal: only the "header" is allowed } /* Note the lines commented out. An interface is NOT a data structure, and therefore cannot contain instance variables. You cannot create an "instance" of an interface. You must have a *class* that implements the interface before any objects can be created. The only kind of variables you may declare inside an interface are *static final* variables, in other words, global constants. You also do not normally implement any functions with code inside curly braces. It's the specification that certain functions must exist that's important. There is however, a way to define a default implementation of a function with the "default" keyword, so function h above, if "return 2" is its default implementation, must be written inside the interface as default int h() { return 2; } Default implementations can be replaced (overridden) in classes that implement the interface. They may be appropriate in some situations, but remember that the main role of an interface is SPECIFICATION and NOT IMPLEMENTATION. Finally, anything you declare inside an interface is automatically "public" so don't write private/protected/public before declarations. The whole purpose of the interface is to declare what must be publically available in classes that implement it. */ class A // superclass { private int x; protected int y; public A(int a, int b) { x=a; y=b; } // constructor public int f() { return x; } public void g() { x += y; } }//A class B extends A implements I // subclass { private int z; public B(int a, int b, int c) // subclass constructor { super(a,b); // calls superclass (A) constructor z = c; } // A.f() is inherited public void g() // overrides A.g { y += z; super.g(); // calls superclass version of g } public int h() { return z; } }//B /* Note that class A does not implement interface I because it does not have an implementation for int h(). Class B does implement I because it provides g() and h(), and f() as well because it's inherited from A. "super" is a keyword in Java: in the constructor of the subclass, it is used to invoke the constructor of the superclass. It is also used to refer to a superclass method that's been overridden. Subtlety: The variable x in A is marked private, so we cannot directly refer to it in the subclass. However, this does not mean that it doesn't exist: it's not visible, but it exists. Otherwise what value is f() returning? */ // we can now use B, for example, as follows: public class interfacenotes { public static void main(String[] av) { B x = new B(2,4,6); x.g(); System.out.println( x.f() ); // prints 12 I y = new B(2,4,6); // different static versus dynamic type. y.g(); // also calls B.g } } /* A class "implements" an interface and "extends" another class; an interface can also extend another interface. "extends" means inherit: all definitions in the parent interface are included in the new interface: */ interface I2 extends I { // f, g, h declarations inherited from I. void f2(); } /* I2 is equivalent to an interface containing f, g, h and f2. In java, "extends" represents an "is a" relationship: an object of type I2 is also an object of type I (this is called "public inheritance" in C++). A class that implements I2 is inferred to also implement I. QUIZ: Can an interface extend class? (if you think yes, try it) Can an interface implement an interface? Read notes above before answering. Can you create an instance of an interface? (I x = new I()?). */ /* Now for a more practical example, but first we must mention Generics: when writing an interface, class, or method we can use *generic type variables*. For example, interface I ... // generic interface with type variables T1, T2 class A ... // generic class with type variable T public int f(TY x) // generic method with type variable TY The following is a built-in Java interface: public interface Comparable { int compareTo(T x); } Many built-in Java classes, including String, Integer, Double, etc. already implement this interface. That is, the built-in String class would have the following form: public class String implements Comparable { // .... public int compareTo(String x) { // returns int based on alphabetical ordering of strings } } Sometimes, in addition to the code of the interface, other requirements must also be met. Given two strings a and b, a.compareTo(b) must return 0 if a and b are to considered "equal", a negative value if a is to be considered "less than" b, and a positive value if a is to be considered "greater than" b. The built-in compareTo function of the String class compares strings by the alphabetical ordering. The interface allows us to write *polymorphic* code. For example, a */ class ordering> { T[] A; // an array of values of type T public T largest() // returns "largest" value in A { if (A==null) return null; // null can be of any reference type T answer = A[0]; for(int i=1;i0) // if A[i] is greater than answer answer = A[i]; return answer; } } /* The expression "T extends Comparable" means that the class ordering can only use types that are consistent with the Comparable interface. Note that T "extends" instead of implements Comparable: this indicates that, when writing generic code that refers to T, we should think of it as an interface (more abstract than a class). class ordering can now be instantiated by any class that implements the appropriate Comparable interface. It is also possible to write a method that's polymorphic by itself, inside any class. Such methods are usually static. The following function takes a generic array to process as an argument: public static > T largest(T[] A) { if (A==null) return null; T answer = A[0]; for(int i=1;i0) answer = A[i]; return answer; } // usage: Integer[] A = {2,5,1,6,3}; System.out.println(largest(A)); // prints 6 String[] B = {"abc","xyz","ghi"}; System.out.println(largest(B)); // prints "xyz", alphabetically largest Also, you can now define your own classes as follows: class student implements Comparable { String name; int idnumber; // ... boring stuff skipped public int compareTo(student other) { return this.idnumber - other.idnumber; } // this function compares students by their id number } Now you can also use your polymorphic method on arrays of students, and it will return the student with the largest id number. */