1

so i was trying to understand the interfaces, but i almost only see articles that explains "how" to use the interface, my problem is to understand the "why" :
so it's better to use Interface than creating and subclassing a class, which might be useless,
so we implement the interface methods in the class, but i don't understand why this is a good thing,

Let's say :
a class like Car.java defines all the code to make the car
we create the interface Working.java with several methods like start(), stop(), etc.
we implement the methods in Diesel_Car.java, Electric_Car.java, etc.
so what does it change for Car.java? This might not be the best example, as it seems that Car should be the parent of Diesel_Car.java etc,
but what was the meaning to implement the methods in those classes?
Is there a method in Car.java that somehow "calls" the Diesel_Car.java class and its interface methods?

I've read that the interface is like a "Contract", but i only see the second part of this contract (where the method is implemented) and i'm having some trouble to imagine where the first part happen?

Thanks for your help

Paul
  • 6,108
  • 14
  • 72
  • 128
  • possible duplicate of [Class vs. Interface](http://stackoverflow.com/questions/2271104/class-vs-interface) – Brian Roach Jan 10 '12 at 13:23
  • The "first part" is the *definition* of the contract, the second part is the implementation. It's a "good thing" because it means functionality is implementation-independent (I can treat every implementation as a Car), and a class can implement multiple interfaces. – Dave Newton Jan 10 '12 at 13:24
  • This question has been asked before, see http://stackoverflow.com/questions/416331/java-interfaces –  Jan 10 '12 at 13:24
  • @Dave Newton : thanks Dave, i'm still a bit confused, even though i've read all the "rules" to use an interface... maybe would you have an example that makes everything more clear? – Paul Jan 10 '12 at 14:16
  • @Paul Added (highly) contrived example as answer for formatting purposes. – Dave Newton Jan 10 '12 at 14:38

5 Answers5

1

Lets take your example of a Base class of Car with Electric_Car and Diesel_Car Subclasses, and expand the model a bit.

Car may have the following Interfaces

  1. Working : with start() & stop() methods
  2. Moving : with move(), turn() & stop() methods

The Car might contain an instance of class AirConditioner which should also implement the interface Working.

The Driver object can interact with objects than implement Working , the driver can start() or stop() . (The driver can start or stop the car and the A/C seperatly).

also, since the Driver can walk around on his own (and does not always need a car) he should implement the interface Moving. The object Ground can now interact with anything that implements Moving : either car or driver.

Nitzan Volman
  • 1,809
  • 3
  • 17
  • 31
  • thanks Nitzan, i think i'm starting to understand it a bit more, but i'm still a bit lost. Would you have another example to describe interfaces? i would really appreciate – Paul Jan 10 '12 at 14:07
  • I'll try to think of another example, Still trying to understand exactly what it is you are having difficulty with. In the above example, what is still missing for you? – Nitzan Volman Jan 10 '12 at 18:52
  • i'm wondering in which context Ground would need to deal with a Car, and then change the type of Car to be a Driver. It's more the "why" to use an interface. – Paul Jan 10 '12 at 18:59
  • maybe Ground is not the best choice here, but suppose for the sake of the example that the Ground controls the movement of every object thats on it, by calling move() turn() & stop() The Ground might need to hold a List allObjects; so it can iterate through all of the objects to move them. In order for an object top be on this Ground, this object must implement the Moving interface – Nitzan Volman Jan 10 '12 at 20:13
  • 1
    Okay, so i think something helped me understand it : if we make future changes to our classes (Car, Driver, etc.), the interfaces are a good way to update the code : let's say we have a `Driver`, with or without a licence, the `Driver` will be implemented in a class like `World` (just for the example) --> so instead of changing several times the code, the hierarchy, and all the classes where `Driver` is used, we could just create the `Driver` interface, and implement either `Driver driver1 = new DriverWithLicence()` or `driver1 = new DriverWithoutLicence()`, and that's it! – Paul Jan 11 '12 at 18:01
  • Both classes would implement their particularities, and `drive1` would be used exactly the same way as before in our `World` class : we have modified the `behavior` of driver1, not the whole object `Driver` and the way it is used by `World` : it makes the code easier to update! – Paul Jan 11 '12 at 18:04
1

(Very) contrived example (non-generic, error handling removed, etc. for clarity).

List theList = new ArrayList();

theList is a List, in this case implemented by an ArrayList. Let's say we pass this to a third-party API that somewhere in its bowels adds something to the list.

public void frobList(List list) {
    list.add(new Whatever());
}

Now let's say for some reason we want to do something unusual to items that are added to the list. We can't change the third-party API. We can, however, create a new list type.

public FrobbableList extends ArrayList {
    public boolean add(E e) {
        super.add(Frobnicator.frob(e));
    }
}

Now in our code we change the list we instantiate and call the API as before:

List theList = new FrobbableList();
frobber.frobList(theList);

If the third-party API had taken an ArrayList (the actual type) instead of a List (the interface), we'd be unable to do this as easily. By not locking the API in to a specific implementation, it provided us the opportunity to create custom behavior.

Taken further, this is a concept fundamental to extensible, debuggable, testable code. Things like dependency injection/Inversion of Control rely on coding to interfaces to function.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
1

I am making another attempt to explain the concept of interface as a contract.

A typical usage scenario is when you'd like to sort a List of elements using java.util.Collections : <T extends java.lang.Comparable<? super T>> void sort(java.util.List<T> ts)

what does this signature mean? the sort() method will accept a java.util.List<T> of objects of type T, where T is an object that implements the interface Comparable.

so, If you would like to use Collections.sort() with a list of your objects you will need them to implement the Comparable interface:

public interface Comparable<T>   {   
    int compareTo(T t);
}

So, if you implement a class of type Car and want to compare cars by their weight using Collections.sort(), you will have to implement the Comparable interface/contract in class car.

public class Car implements Comparable<Car> {
   private int weight;

   //..other class implementation stuff

   @Override
   public int compareTo(Car otherCar) {
       if (this.weight == otherCar.weight) return 0;
       else if (this.weight > otherCar.weight) return 1;
       else return -1;
   }
} 

under the hood the Collections.sort() will call your implementation of compareTo when it sorts the list.

Nitzan Volman
  • 1,809
  • 3
  • 17
  • 31
  • okay, so the method is like a callback, and the code that deal with this callback is already written somewhere else... okay i think i understand it a bit more, thanks a lot for your answers! – Paul Jan 11 '12 at 14:10
0

The contract is a concept of how classes work with each other. The idea is that a interfacing class defines the methods return type and name, but doesn't provide the idea of how it is implemented. That is done by the implementing class.

The concept is that when a Interface A defines methods A and B, any class implementing that interface MUST implement A and B along with its own methods. So it might work like this:

interface InterfaceA {
    void methodA();
    void methodB(String s);
}

public class ClassA implements InterfaceA {
     public void methodA() { 
         System.out.println("MethodA");
     }

     public void methodB(String s) {
         System.out.println(s);
     }
}

The contract principle is that anything implementing a interface must implement the whole interface. Anything that doesn't do this must be abstract.

Hope this helps.

Ocracoke
  • 1,718
  • 3
  • 24
  • 38
  • thanks MikeyB, this is "what" we should do to use the interface, but not how the thing works, what happens next when the methods are implemented in the class... – Paul Jan 10 '12 at 13:45
  • @Paul What do you mean, "what happens next"? Are you asking how Java method dispatch works? – Dave Newton Jan 10 '12 at 18:30
  • @Dave Newton : okay, it seems that the main point is to be able to change the type of the object we're dealing with (by specifying the Interface as the type of the object), but why would you do that? – Paul Jan 10 '12 at 19:05
  • @Paul For the reason I provided in the example, for DI/IoC, etc. Also, it's not just about changing implementation, but being able to treat a heterogeneous collection as similar types. I heritence is one way of doing that, but in Java, it's limited to a single hierarchy, which isn't always helpful. (Very often not.) – Dave Newton Jan 10 '12 at 19:06
0

Design by contract (DbC), also known as programming by contract and design-by-contract programming, is an approach for designing computer software. It prescribes that software designers should define formal, precise and verifiable interface specifications for software components, which extend the ordinary definition of abstract data types with preconditions, postconditions and invariants. These specifications are referred to as "contracts", in accordance with a conceptual metaphor with the conditions and obligations of business contracts. Wikipedia

Short-cut.

If you follow the good practice of coding against interfaces, you know that the interface defines the contract all implementation classes must adhere to.

We designed Contract Java, an extension of Java in which method contracts are specified in interfaces. We identified three design goals.

  • First, Contract Java programs without contracts and programs with fully-satisfied contracts should behave as if they were run without contracts in Java.
  • Second, programs compiled with a conventional Java compiler must be able to interoperate with programs compiled under Contract Java.
  • Finally, unless a class declares that it meets a particular contract, it must never be blamed for failing to meet that contract. Abstractly, if the method m of an object with type t is called, the caller should only be blamed for the pre-condition contracts associated with t and m should only be blamed for post-condition contracts associated with t. These design goals raise several interesting questions and demand decisions that balance language design with software engineering concerns. This section describes each of the major design issues, the alternatives, our decisions, our rationale, and the ramifications of the decisions. The decisions are not orthogonal; some of the later decisions depend on earlier ones.

Contracts in Contract Java are decorations of methods signatures in interfaces. Each method declaration may come with a pre-condition expression and a post-condition expression; both expressions must evaluate to booleans. The pre-condition specifies what must be true when the method is called. If it fails, the context of the method call is to blame for not using the method in a proper context. The post-condition expression specifies what must be true when the method returns. If it fails, the method itself is to blame for not establishing the promised conditions. Contract Java does not restrict the contract expressions. Still, good programming discipline dictates that the expressions should not contribute to the result of the program. In particular, the expressions should not have any side-effects. Both the pre- and post-condition expressions are parameterized over the arguments of the method and the pseudovariable this. The latter is bound to the current object. Additionally, the post-condition of the contract may refer to the name of the method, which is bound to the result of the method call. Contracts are enforced based on the type-context of the method call. If an object’s type is an interface type, the method call must meet all of the contracts in the interface. For instance, if an object implements the interface I, a call to one of I’s methods must check that pre-condition and the post-condition specified in I. If the object’s type is a class type, the object has no contractual obligations. Since a programmer can always create an interface for any class, we leave objects with class types unchecked for efficiency reasons. For an example, consider the interface RootFloat:

interface RootFloat {
    float getValue ();
    float sqRoot ();
    @pre { this.getValue() >= 0f }
    @post { Math.abs(sqRoot * sqRoot - this.getValue()) < 0.01f }
}

It describes the interface for a float wrapper class that provides a sqRoot method. The first method, getValue, has no contracts. It accepts no arguments and returns the unwrapped float. The sqRoot method also accepts no arguments, but has a contract. The pre-condition asserts that the unwrapped value is greater than or equal to zero. The result type of sqRoot is float. The post-condition states that the square of the result must be within 0.01 of the value of the float. Even though the contract language is sufficiently strong to specify the complete behavior in some cases, such as the previous example, total or even partial correctness is not our goal in designing these contracts. Typically, the contracts cannot express the full behavior of a method. In fact, there is a tension between the amount of information revealed in the interface and the amount of validation the contracts can satisfy. For an example, consider this stack interface:

interface Stack {
    void push (int i);
    int pop ();
}

With only push and pop operations available in the interface, it is impossible to specify that, after a push, the top element in the stack is the element that was just pushed. But, if we augment the interface with a top operation that reveals the topmost item on the stack (without removing it), then we can specify that push adds items to the top of the stack:

interface Stack {
     void push (int x);
     @post { x = this.top() }
     int pop ();
     int top ();
}

In summary, we do not restrict the language of contracts. This makes the contract language as flexible as possible; contract expression evaluation may even contribute to the final result of a computation. Despite the flexibility of the contract language, not all desirable contracts are expressible. Some contracts are inexpressible because they may involve checking undecidable properties, while others are inexpressible because the interface does not permit enough observations.

Lion
  • 18,729
  • 22
  • 80
  • 110