public class Advanced { public static void main(String args[]) { System.out.println("\nAdvanced.main()"); C c = new C("Just Some String"); // C "is a" A c.y(); // y() is in A } } abstract class A { public static final int MYCONSTANT = 99; // constant public static int m = 3; // class variable, visible to world public int i = 1; // instance variable, visible to world protected int j = 2; // visible to derived (sub) classes, package private int k; // only visible within A private String s; // String is a Java object private D d = new D(); // Composition: d is a handle or reference // A uses d public A() { // default constructor this(""); // call the next constructor, using default "" System.out.println("A()"); // typical output } public A(String s) { // call the next constructor, using default 0 this(s,0); System.out.println("A(s): s=" + s); // concat strings with + } public A(String s, int k) { // powerful constructor System.out.println("A(s,k): s="+s+" k="+k);// polymorphism: k can be treated as string this.s = s; // this.s is private var, s is param this.k = k; // this.k is private var, s is param d.s(); // use handle d to call s() } public abstract void x(); // derived classes must overload abstract methods public final void y() { // cannot overload final methods System.out.println("A.y()"); x(); // will go down and execute code in B } public void z() { // may overload instance method System.out.println("A.z(): m=" + m); // instance method accessing static var System.out.println("A.z(): m=" + A.m); // instance method accessing static var q(); // instance can call static, or call A.q() } public static void q() { // class method accessed via class name A System.out.println("A.q(): m=" + m); // class method accessing static var System.out.println("A.q(): m=" + A.m); // class method accessing static var //System.out.println("A.q(): i=" + i); // class method cannot access instance var } protected D getD() { // only derived classes can access (and package) System.out.println("A.getD()"); return d; // return the handle to d } } interface B { // no vars, no code, just specify required ops public void t(); // just like an abstract method } class C extends A implements B { // C inherits A's vars and code // C inherits responsibility to implement B's ops private D d; // Composition private int i = 7; // this.i different than super.i public C(String s) { // constructor super(s); // pass s to A's constructor System.out.println("C(s): s=" + s); d = getD(); // call inherited method to get handle to d d.s(); // "use" d } public void x() { // must implement super's abstract method System.out.println("C.x(): m=" + A.m); // instance method accessing static var z(); } public void z() { // overload super's method System.out.println("C.z()"); super.z(); // but can still call super's version of z() r(); // only C can call private helper function } private void r() { // additional method beyond super's methods System.out.println("C.r(): i=" + i); // i is local to C System.out.println("C.r(): i=" + this.i); // same i System.out.println("C.r(): i=" + super.i); // i from the super (base) class t(); } public void t() { // must implement all interface methods System.out.println("C.t()"); } } class D { // "used" by A and C public void s() { System.out.println("D.s()"); } }