/* 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 first line (int f(int x)) is the specfication 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 (however, methods and instance variables are overriden in different ways - more on that later). An interface, on the other hand, 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 cover that 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. *NOTE: recent changes to Java allow "default" function defintions in interfaces (and static final variables) but these are not essential features and don't allow them to confuse you about what an interface is for: it's intended to be ABSTRACT. 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 } 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" implements an "is a" relationship: an object of type I2 is also an object of type I. A class that implements I2 is inferred to also implement I. 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 the 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. */