Chapter 8 Interfaces and inner classes We learnt
- Slides: 31
Chapter 8: Interfaces and inner classes ● We learnt a number of mechanisms to abstract concepts and reuse them: – – – ● ● Data abstraction (Encapsulation and Information Hiding) – making classes Reuse by Inheritance and Composition Polymorphism for making extensible programs Interfaces are another usefull mechanism in Java for better program construction Inner classes (classes inside classes) are another concept introduced in Java
Interfaces ● ● We know that public members of a class specifies the interface for that class With abstract classes and inheritance we could make interface without any specific implementation and leave the implementation for the derived classes Interface concept is a step further by specifying an interface without any specific implementation This is a powerfull tool for high quality software production: – – Write client code for Interface Then any implementation can be used at runtime
Interfaces (Cont. ) ● ● ● We can think of an Interface as a Pure Abstract class (no method is implemented) Only method names, argument list and return types are specified without method bodies An interface can also contains fields but the fields are implicitly static and final An interface says: “This is what all classes that implement this interface will look like” So an interface makes a protocol between classes
Interface example
Interface example (cont. ) interface Instrument { // Compile-time constant: int I = 5; // static & final // Cannot have method definitions: void play(Note n); // Automatically public String what(); void adjust(); } class Wind implements Instrument { public void play(Note n) { System. out. println("Wind. play() " + n); } public String what() { return "Wind"; } public void adjust() {} } class Percussion implements Instrument { public void play(Note n) { System. out. println("Percussion. play() " + n); } public String what() { return "Percussion"; } public void adjust() {} } class Stringed implements Instrument { public void play(Note n) { System. out. println("Stringed. play() " + n); } public String what() { return "Stringed"; } public void adjust() {} } class Brass extends Wind { public void play(Note n) { System. out. println("Brass. play() " + n); } public void adjust() { System. out. println("Brass. adjust()"); } } class Woodwind extends Wind { public void play(Note n) { System. out. println("Woodwind. play() " + n); } public String what() { return "Woodwind"; } }
Interface example (cont. ) public class Music 5 { private static Test monitor = new Test(); // Doesn't care about type, so new types // added to the system still work right: static void tune(Instrument i) { //. . . i. play(Note. MIDDLE_C); } static void tune. All(Instrument[] e) { for(int i = 0; i < e. length; i++) tune(e[i]); } public static void main(String[] args) { // Upcasting during addition to the array: Instrument[] orchestra = { new Wind(), new Percussion(), new Stringed(), new Brass(), new Woodwind() }; tune. All(orchestra); monitor. expect(new String[] { "Wind. play() Middle C", "Percussion. play() Middle C", "Stringed. play() Middle C", "Brass. play() Middle C", "Woodwind. play() Middle C" }); } }
Multiple inheritance ● ● In C++ there is multiple inheritance mechanism (i. e. inheriting from several classes) But its usage is sometimes complicated and confusing – ● ● What happens if class A inherits from B and C, which both have a method with the same signature? Java designers deceided to have single inheritance to prevent such confusion But with interface mechanism we can simulate multiple imheritance
Multiple inheritance (cont. )
Multiple inheritance (cont. ) interface Can. Fight { void fight(); } interface Can. Swim { void swim(); } interface Can. Fly { void fly(); } class Action. Character { public void fight() {} } class Hero extends Action. Character implements Can. Fight, Can. Swim, Can. Fly { public void swim() {} public void fly() {} } public class Adventure { public static void t(Can. Fight x) { x. fight(); } public static void u(Can. Swim x) { x. swim(); } public static void v(Can. Fly x) { x. fly(); } public static void w(Action. Character x) { x. fight(); } public static void main(String[] args) { Hero h = new Hero(); t(h); // Treat it as a Can. Fight u(h); // Treat it as a Can. Swim v(h); // Treat it as a Can. Fly w(h); // Treat it as an Action. Character } } ///: ~
Interface or Abstract class? ● ● The first choice is interface The benefit is that client code is not bound to any implementation – With abstract classes, your client code is bound to an class hierarchy – With interface any object of any class hierarchy that implements the interface is ok Use abstract classes when some common behavior should be implemented and reused As much as possible write client code to work with interfaces not any implementation (abstract or concrete classes) – This is critical for software that should be extended
Name collisions with interfaces interface I 1 { void f(); } interface I 2 { int f(int i); } interface I 3 { int f(); } class C { public int f() { return 1; } } class C 2 implements I 1, I 2 { public void f() {} public int f(int i) { return 1; } // overloaded } class C 3 extends C implements I 2 { public int f(int i) { return 1; } // overloaded } class C 4 extends C implements I 3 { // Identical, no problem: public int f() { return 1; } } // Methods differ only by return type: //! class C 5 extends C implements I 1 {} //! interface I 4 extends I 1, I 3 {} ///: ~ Interface. Collision. java: 23: f( ) in C cannot implement f( ) in I 1; attempting to use incompatible return type found : int required: void Interface. Collision. java: 24: interfaces I 3 and I 1 are incompatible; both define f( ), but with different return type
Extending an interface Monster { void menace(); } interface Dangerous. Monster extends Monster { void destroy(); } interface Lethal { void kill(); } class Dragon. Zilla implements Dangerous. Monster { public void menace() {} public void destroy() {} } interface Vampire extends Dangerous. Monster, Lethal { void drink. Blood(); } class Very. Bad. Vampire implements Vampire { public void menace() {} public void destroy() {} public void kill() {} public void drink. Blood() {} } public class Horror. Show { static void u(Monster b) { b. menace(); } static void v(Dangerous. Monster d) { d. menace(); d. destroy(); } static void w(Lethal l) { l. kill(); } public static void main(String[] args) { Dangerous. Monster barney = new Dragon. Zill u(barney); v(barney); Vampire vlad = new Very. Bad. Vampire(); u(vlad); v(vlad); w(vlad); } } ///: ~
Grouping constants in an interface ● ● Since any fields we put in an interface is static and final, interface is a convenient tool to create group of constants This way it is like enum in C/C++ public interface Months { int JANUARY = 1, FEBRUARY = 2, MARCH = 3, APRIL = 4, MAY = 5, JUNE = 6, JULY = 7, AUGUST = 8, SEPTEMBER = 9, OCTOBER = 10, NOVEMBER = 11, DECEMBER = 12; } ///: ~
Initializing fields in interfaces public class Test. Rand. Vals { public interface Rand. Vals { private static Test monitor = new Test(); Random rand = new Random(); public static void main(String[] args) { int random. Int = rand. next. Int(10); System. out. println(Rand. Vals. random. Int); long random. Long = rand. next. Long() * 10; System. out. println(Rand. Vals. random. Long); float random. Float = rand. next. Long() * 10; double random. Double = rand. next. Double() * 10; System. out. println(Rand. Vals. random. Float); System. out. println(Rand. Vals. random. Double); } monitor. expect(new String[] { "%% -? \d+", "%% -? \d\. \d+E? -? \d+" }); } } ///: ~
Nesting interfaces class A { interface B { void f(); } public class BImp implements B { public void f() {} } private class BImp 2 implements B { public void f() {} } public interface C { void f(); } class CImp implements C { public void f() {} } private class CImp 2 implements C { public void f() {} } private interface D { void f(); } private class DImp implements D { public void f() {} } public class DImp 2 implements D { public void f() {} } public D get. D() { return new DImp 2(); } private D d. Ref; public void receive. D(D d) { d. Ref = d; d. Ref. f(); } } interface E { interface G { void f(); } // Redundant "public": public interface H { void f(); } void g(); // Cannot be private within an interface: //! private interface I {} }
Nesting interfaces (Cont. ) public class Nesting. Interfaces { public class BImp implements A. B { public void f() {} } class CImp implements A. C { public void f() {} } // Cannot implement a private interface except // within that interface's defining class: //! class DImp implements A. D { //! public void f() {} //! } class EImp implements E { public void g() {} } class EGImp implements E. G { public void f() {} } class EImp 2 implements E { public void g() {} class EG implements E. G { public void f() {} } } public static void main(String[] args) { A a = new A(); // Can't access A. D: //! A. D ad = a. get. D(); // Doesn't return anything but A. D: //! A. DImp 2 di 2 = a. get. D(); // Cannot access a member of the interface: //! a. get. D(). f(); // Only another A can do anything with get. D(): A a 2 = new A(); a 2. receive. D(a. get. D()); } } ///: ~
Inner classes ● ● ● We can put definitions of classes inside other classes. Those classes are named as inner classes With inner classes we can group related class definitions and control access to them Inner classes concept is different from composition
Making inner classes public class Parcel 1 { class Contents { private int i = 11; public int value() { return i; } } class Destination { private String label; Destination(String where. To) { label = where. To; } String read. Label() { return label; } } // Using inner classes looks just like // using any other class, within Parcel 1: public void ship(String dest) { Contents c = new Contents(); Destination d = new Destination(dest); System. out. println(d. read. Label()); } public static void main(String[] args) { Parcel 1 p = new Parcel 1(); p. ship("Tanzania"); } } ///: ~
Returing objects of inner class type public class Parcel 2 { class Contents { private int i = 11; public int value() { return i; } } class Destination { private String label; Destination(String where. To) { label = where. To; } String read. Label() { return label; } } public Destination to(String s) { return new Destination(s); } public Contents cont() { return new Contents(); } public void ship(String dest) { Contents c = cont(); Destination d = to(dest); System. out. println(d. read. Label()); } public static void main(String[] args) { Parcel 2 p = new Parcel 2(); p. ship("Tanzania"); Parcel 2 q = new Parcel 2(); // Defining references to inner classes: Parcel 2. Contents c = q. cont(); Parcel 2. Destination d = q. to("Borneo"); } } ///: ~
Inner classes and upcasting ● ● What is the usage for inner classes. If it is for hidding, we can have same effects with package access class definition One usage is with upcasting This way you can completely hide the implementation
Inner classes and upcasting (cont. ) //: c 08: Destination. java public interface Destination { String read. Label(); } ///: ~ //: c 08: Contents. java public interface Contents { int value(); } ///: ~ public class Test. Parcel { public static void main(String[] args) { Parcel 3 p = new Parcel 3(); Contents c = p. cont(); Destination d = p. dest("Tanzania"); // Illegal -- can't access private class: //! Parcel 3. PContents pc = p. new PContents(); } } ///: ~ class Parcel 3 { private class PContents implements Contents { private int i = 11; public int value() { return i; } } protected class PDestination implements Destination { private String label; private PDestination(String where. To) { label = where. To; } public String read. Label() { return label; } } public Destination dest(String s) { return new PDestination(s); } public Contents cont() { return new PContents(); } }
Inner classes in methods and scops ● ● We can define inner classes inside a method or a scop! Why we need that? – – You want to create a refrence that implements an interface. The implementation is only used inside the method or scope and there is no need that other parts of code (the owner class or others know about that implementation)
Inner classes in methods and scops(cont. ) ● For example we can do following: – – – Define a class inside a method Define a class within a scope inside a class Define an anonymous class implementing an interface Define an anonymous class that performs field initialization Define an anonymous class that performs constructuion using instance initialization
Definining Inner classes in methods public class Parcel 4 { public Destination dest(String s) { class PDestination implements Destination { private String label; private PDestination(String where. To) { label = where. To; } public String read. Label() { return label; } } return new PDestination(s); } public static void main(String[] args) { Parcel 4 p = new Parcel 4(); Destination d = p. dest("Tanzania"); } } ///: ~
Nesting inner class in a scope public class Parcel 5 { private void internal. Tracking(boolean b) { if(b) { class Tracking. Slip { private String id; Tracking. Slip(String s) { id = s; } String get. Slip() { return id; } } Tracking. Slip ts = new Tracking. Slip("slip"); String s = ts. get. Slip(); } // Can't use it here! Out of scope: //! Tracking. Slip ts = new Tracking. Slip("x"); } public void track() { internal. Tracking(true); } public static void main(String[] args) { Parcel 5 p = new Parcel 5(); p. track(); } } ///: ~
Annonymous inner classes public class Parcel 6 { public Contents cont() { return new Contents() { private int i = 11; public int value() { return i; } }; // Semicolon required in this case } public static void main(String[] args) { Parcel 6 p = new Parcel 6(); Contents c = p. cont(); } } ///: ~ This is a shorthand for: class My. Contents implements Contents { private int i = 11; public int value() { return i; } } return new My. Contents();
Annonymous inner classes with arguments for base class constructor public class Wrapping { private int i; public Wrapping(int x) { i = x; } public int value() { return i; } } ///: ~ public class Parcel 7 { public Wrapping wrap(int x) { // Base constructor call: return new Wrapping(x) { // Pass constructor argum public int value() { return super. value() * 47; } }; // Semicolon required } public static void main(String[] args) { Parcel 7 p = new Parcel 7(); Wrapping w = p. wrap(10); } } ///: ~
Field initialization in anonymous class public class Parcel 8 { // Argument must be final to use inside // anonymous inner class: public Destination dest(final String dest) { return new Destination() { private String label = dest; public String read. Label() { return label; } }; } public static void main(String[] args) { Parcel 8 p = new Parcel 8(); Destination d = p. dest("Tanzania"); } } ///: ~
Constructor for anonymous inner classes? ● ● ● public class Anonymous. Constructor { private static Test monitor = new Test(); public static Base get. Base(int i) { return new Base(i) { { System. out. println("Inside instance initializer" } public void f() { System. out. println("In anonymous f()"); } }; } public static void main(String[] args) { Base base = get. Base(47); base. f(); monitor. expect(new String[] { "Base constructor, i = 47", "Inside instance initializer", "In anonymous f()" }); } } ///: ~ Since anonymous inner classes has no name, we can't define constructors for them What to do when we need some initializations? We can do initialization in a block inside the class abstract class Base { public Base(int i) { System. out. println("Base constructor, i = " + i); } public abstract void f(); }
Instance initialization for parcel class Parcel 9 { example public private static Test monitor = new Test(); public Destination dest(final String dest, final float price) { return new Destination() { private int cost; // Instance initialization for each object: { cost = Math. round(price); if(cost > 100) System. out. println("Over budget!"); } private String label = dest; public String read. Label() { return label; } }; } public static void main(String[] args) { Parcel 9 p = new Parcel 9(); Destination d = p. dest("Tanzania", 101. 395 F); monitor. expect(new String[] { "Over budget!" }); } } ///: ~
Link to the outer class public Selector get. Selector() { interface Selector { boolean end(); Object current(); void next(); } public class Sequence { private static Test monitor = new Test(); private Object[] objects; private int next = 0; public Sequence(int size) { objects = new Object[size]; } public void add(Object x) { if(next < objects. length) objects[next++] = x; } private class SSelector implements Selector { private int i = 0; public boolean end() { return i == objects. length; } public Object current() { return objects[i]; } public void next() { if(i < objects. length) i++; } } return new SSelector(); } public static void main(String[] args) { Sequence sequence = new Sequence(10); for(int i = 0; i < 10; i++) sequence. add(Integer. to. String(i)); Selector selector = sequence. get. Selector(); while(!selector. end()) { System. out. println(selector. current()); selector. next(); } monitor. expect(new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }); } } ///: ~
- By listening to my inner defender voice i can be sure that
- Difference between abstract classes and interfaces
- Interface and abstract class difference in java
- Inner critic and inner defender
- Classe e subclasse de onde
- Pre ap classes vs regular classes
- The chappals were given to the beggar because
- Interface and dialogue design
- Gui events
- Example of colloids
- Expressive interface
- [web user interface]
- Uml interfaces are used to:
- Office interface vs industrial interface
- Expressive interface
- Blueprint interfaces
- Which is not an objective of designing interfaces?
- Property management system interface
- Similar to
- Joe hogan openet
- Toggle reveal tools
- Bts um
- Expressive interfaces
- Hardware interfaces in srs example
- Team interfaces
- Operacion de micros e interfaces
- Why are user interfaces hard to implement
- Design heuristic
- Multiple document interface
- Programming graphical user interfaces in r
- Interfaces inteligentes
- Interfaces