Why use the comparable interface in Java? - java

I wanted to ask why we use the comparable interface in java? Wouldn't it be simpler to just make the compareTo method without using the comparable interface?
Instead of doing this:
//some class that implements comparable
public int compareTo(someClass someInstanceOfThatClass) {
// do stuff that returns -1,0,or 1
}
Why can't we just do this:
//some class that does NOT implement comparable, but we still
//make a compareTo method
public int compareTo(someClass someInstanceOfThatClass) {
// do stuff that returns -1,0, or 1
}
I guess my question is why do we bother implementing comparable, if we could just make a compareTo method without being forced to by some interface (comparable)?

Comparable is an interface, hence it imposes a contract that others may follow. For example, calling Collections.sort(list) only works if the elements are instances of Comparable, and internally relies on the compareTo method to implement the sorting.

Java's type system is nominal, not structural, so simply having the method required by the interface is not enough to implement it; you also have to declare that the class implements the interface. In some other languages such as Typescript, having the method with the right signature would be enough, but Java is not like that.
If you are only calling the compareTo method from your own code then this may not matter, but if you are using classes or methods from the standard library or from other libraries which take Comparable things as arguments, then your class will need to implement the interface so you can pass your objects to them.

I think it returns to the innate concept of the interface.
You always sure that every class which has implemented Comparable interface, has ability to be compared and sometimes you need this assurance.
For example if you have a method that have a parameter with Comparable type, then you are sure that comapreTo is implemented with that parameter and this parameter issemantically comparable.
But whitout interface you can't get this assurance.

Related

Java and Comparable

I'm new here and this is my first post. I've just completed my Java OCA and now moving onto studying for the OCP. I have a question regarding Comparable interface.
I have this code snippet which explains how Comparable is implemented:
import java.util.*;
public class Duck implements Comparable<Duck> {
private String name;
public Duck(String name) {
this.name = name;
}
public String toString() { // use readable output
return name;
}
public int compareTo(Duck d) {
return name.compareTo(d.name); // call String's compareTo
}
public static void main(String[] args) {
List<Duck> ducks = new ArrayList<>();
ducks.add(new Duck("Quack"));
ducks.add(new Duck("Puddles"));
Collections.sort(ducks); // sort by name
System.out.println(ducks); // [Puddles, Quack]
}
}
I more or less understand what is goin on here but below this code snippet the author quotes that:
The Duck class implements the Comparable interface. Without implementing that interface, all we have is a method named compareTo(), but it wouldn't be a Comparable object.
My question is why would it not be comparable? Is this something to do with the fact that calling code such as the Collections.sort() would internally use the Comparable type as a reference parameter to compare any object?
Thanks in advance for any help and I hope my question makes sense.
Java is a Object Oriented Based language. Which supports inheritance through classes/ polymorphism through class/abstract class/interface
interface Comparable<T> {
// methods
}
class Person implements Comparable<Person> {
//methods
}
This essentially means any object of the Type Person is also of the Comparable Type.
interface Runnable {}
class Task implements Runnable {}
this means any object created of Task class is also of the Runnable Type.
This is what the author means.
If you do not implement Comparable interface, yet define the compareTo() method, you are just defining a method inside the class, as any other method. YOU ARE NOT OVERRIDING THE compareTo() method in the Comparable interface defined.
You can still compare each object using your compareTo() method, but you need to define your own sort method which internally would call compareTo() method to get the list in a sorted way.
The Java API Collections.sort() internally converts the list to an Object[] and calls the Arrays.sort(). Now Arrays.sort() will use a modified version of the TimSort Algorithm for sorting and the contract is - it does the sorting of elements of the Array only if they are of the Comparable Type.
ComparableTimSort
Collections.sort()
You can check, for all of the internal calls, it states clearly :
#throws IllegalArgumentException (optional) if the comparator is
found to violate the {#link Comparator} contract
So to pass any Object Types to the sort() it has to be also of the type Comparable. Strings/Wrappers are already of the Comparable Type. Hence you need to take care of this contract while defining your user defined objects.
"Without implementing that interface, all we have is a method named compareTo(), but it wouldn't be a Comparable object."
-Simply put, it means without implementing the interface, you have a Duck type object, NOT comparable type
My question is why would it not be comparable? Is this something to do with the fact that calling code such as the Collections.sort() would internally use the Comparable type as a reference parameter to compare any object?
I'm not sure what you exactly mean by reference parameter.
In Java, it is not enough for a class to provide implementation for a method on an interface (or a class) to become that type. It has to be explicitly mentioned in the class declaration.
There are two overloaded sort utility methods on the Collection class.
public static <T extends Comparable<? super T>> void sort(List<T> list)
public static <T> void sort(List<T> list, Comparator<? super T> c)
When your class implements Comparable, you can pass just the list of objects of that class in the first method. If it does not implement Comparable, it will not compile as the bounds for T must extend Comparable. In that case, you will be forced to pass an explicit Comparator to compare the objects.
As the author of the book mentioned, having a method whose signature is the same as the method in an arbitrary interface (or class) does not make it of that type.
Duck Typing does not work in Java

Methods That Return an Object of an Interface Type

All beginners like myself, always get confused to see a method returns an object of an interface type, because interfaces have abstract methods, thus cannot be instantiated.
I finally figured out a way to understand this:
((when we say that a method returns an object of an interface type, we are actually implicitly saying that the method in fact returns an object/instance of some class that implements that interface, but in most cases that class is unknown because it is declared as anonymous in the implementation of the method. Thus, we refer to the returned object as being of that interface type.)).
Is this explanation correct ?
"...when we say that a method returns an object of an interface type, we are actually implicitly saying that the method in fact returns an object/instance of some class that implements that interface..." - It is correct, but we are saying it explicitly.
The second part of your definition is quite not correct, as #Jon Skeet pointed out. Applying anonymous class in the implementation is a very specific case. Generally, returning an interface gives you more freedom:
It is possible to change implementation of the method to return another object that implements the same interface, without changing code that uses this method.
You leave possibility for extending classes to override the method, so that it returns another object that implements the same interface. Here you can actually change the return type. If method of the base class returned concrete class, e.g., ArrayList, overridden method would have to also return ArrayList or its subclass.
The rule of thumb is the following. If concrete class implements an interface and there is no benefit in returning a concrete class object, e.g., ArrayList, return an interface - List, Collection. This will enhance maintainability of your code, i.e., the code will be easier to change in future.
It's my birthday at the end of this month, so I've added a new method to all my friends and family:
public Present givePresent{
//code to select an appropriate and sufficiently expensive present
return present;
}
There's two things I could do here. I could write a Present class and ensure that all possible presents extend it. But we could run in to all sorts of problems here: BatmanComic already inherits from ComicBook for example, so we'd have to move further and further up the tree until Present is basically indistinguishable from Object. The other way is to look at what is actually happening here. I'm looking to receive something that fits in to a specific category and, in short, Java has two ways of doing that. Inheritance and Interfaces. Creating Present as an interface is achieving exactly the same goal as creating it as an abstract superclass but avoids all problems of multiple inheritance. This way all I have to do is write an interface:
public interface Present{
}
and make sure all the socks and books and whatever implement that.

Comparable Class

I've been trying to learn the comparable class for sometime now, I know the correct syntax and the how it is used in most cases. Such as:
int result = ObjectA.compareTo(ObjectB);
would return a value of 0 if both object is the same; a negative value if object A is less then object B ,or a positive value if A is greater then B.
However when I go to actually write a program that uses the compareTo method, the compiler is saying that it can not find the compareTo method.
my question is: Do I have to directly inherit from the Comparable class in order to use the compareTo method? only reason I'm asking is because you do not have to explicitly inherit methods like toString or equals...because everything inherit from object. Where does CompareTo fall under?
You need to implement the Comparable interface:
public class MyClass implements Comparable<MyClass>
and then declare the compareTo() method:
public int compareTo(MyClass myClass){
//compare and return result
}
Comparable is an interface, not a class. So you would implement the interface, not subclass the class. Additionally, implementing the interface means implementing the compareTo method yourself in your implementing class.
First, it will only work in instances. Don't know if your compare is comparing objects or the classes itself because of your naming. I will assume you are using objects :)
The class you want to compare using #compareTo MUST implement Comparable. Another way to achieve this without having to implement Comparable is providing your sort method a Comparator expecting your class.
Comparable is an interface so you do not "inherit" it (extends), but implement it (implements).
You can write your own compareTo method in your class without specifying the Comparable interface, but then the methods in the API won't know if your object meets the contract that Comparable enforces. So, you won't be able to use methods like Arrays.sort() and the like that expect to work with objects that do enforce Comparable.
If you want the objects of your class A compared, possibly because you like to sort a list of those objects, you need to make the class A implement Comparable interface.
Once the class A implements Comparable it must implement and define the behavior of compareTo, which is essentially how you want two objects of class A be compared.
It it this method where you can decide which fields of the class A take part in evaluating the lesser- or greaterness of an object.

interface and contract : in this example

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
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
Working : with start() & stop() methods
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.
(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.
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.
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.
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.

In java what does extending from a comparable mean

I see code like this
class A implements Comparable<A> {
}
What does this mean, what are the advantages and disadvantages of it?
It means that class is committed to respond to the methods defined by the "interface" Comparable.
The advantage you have with this ( and any other "implements" declaration ) it that you can "abstract" the type of the object and code to the interface instead.
Consider this
class A implements Comparable {
....
}
class B implements Comparable {
....
}
class C implements Comparable {
....
}
You then may code something that can use Comparable instead of a specific type:
public void doSomethingWith( Comparable c ) {
c.compareTo( other ); // something else...
}
And invoke it like:
doSomethingWith( new A() );
doSomethingWith( new B() );
doSomethingWith( new C() );
Because you don't really care what the type of the class is, you just care it does implement the interface.
This ( program to the interface rather to the implementation ) is one of the most powerful techniques in OO programming world, because it promotes low-coupling.
Implementing a comparable interface means that A can be compared with other instances of A.
Many operations in java that involve sorting use the methods defined in the Comparable interface to determine if instances of A are greater then less or equal to other instances.
By implementing these methods you are able to use a lot of handy features such as java sort, use instances of A as keys for binary trees, and more.
It means that class A can be sorted using the Comparable compareTo method:
A a1 = new A(1);
A a2 = new A(3);
// -1, 0, or 1 depending on whether a2 is less than, equal to, or greater than a1
int order = a1.compareTo(a2);
Comparable uses the natural ordering for your class.
Another way to go since Java 5 is Comparator. You can pass this object around and have more than one way to compare and sort the target class. For example, sometimes you might want to sort a Name class by first name, other times by last name. Comparable only gives you one way to do it, but you can have several Comparator instances.
It means that the class is one which can be operated on by functions which expect their arguments to be objects that can be compared with other objects of the same type (such as the pre-defined sorting functionality for lists).
Implementing the Comparable interface means that the class supports certain functions which the interface requires (specifically, the compareTo() method), that the sorting (or other) operations being performed on the class will utilize to do their work without having to care about the rest of the class.
For more details:
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Comparable.html
In addition to what everyone else said, by implementing an interface (or extending a class), you get compiler enforcement of the contract of the supertype. In the case of 'Comparable', that means that you get a compiler error if you fail to implement the 'int compareTo(A anA)' method in the implementing class. Adding the annotation '#Override' to the implementing method provides even more compile-time safety; if you fail to implement the method with the right signature the compiler will tell you. Compile-time errors are much, much easier and cheaper to fix than run-time errors. Furthermore, implementing an interface allows any instance of an implementing class to be treated as the interface type for methods (and constructors) that take the interface type as an argument or generic parameter. For example, the 'java.util.Collections.max(Collection coll)' method takes a collection whose base type must extend 'Comparable'.
http://download.oracle.com/javase/7/docs/api/java/util/Collections.html#max(java.util.Collection)
It means that objects of this class can be easily sorted in collections because they can be compared to each other. The other option is to implement a Comparator which is a class responsible for sorting other classes. The Comparable puts the sorting logic directly in the class to be sorted; the Comparator puts the sorting logic in a different class.

Categories

Resources