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.
Related
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.
Using interface is good approach to provide abstraction and I am usually trying to use it if possible. But this time I have a little bit different case and I am not sure if it is good practice to use here.
I have two different classes which needs some query method with same signature. Lets say MyString and MyInteger.
I was thinking to define an interface with one method:
public interface MyInterface{
// no type is specified for the list, because each implementation will have different type of object
List query();
}
So basically I need to implement two different class which implements the interface above. First one will get List<String>, and second one will get List<Integer> result from the query method.
The thing is I do not like not specifying generic type of in the interface, because I will need to cast later.
So does it make sense to use interface here, or better to implement two separate class with same method signature without common interface ?
The thing is I do not like not specifying generic type of in the interface...
That's exactly how you address this.
When I need to get the object from list lets say Integer x = (Integer)list.get(index); This is just an example, indeed I use user defined object.
The whole point of generics is that you don''t need to do that. Instead:
public interface MyInterface<T> {
List<T> query();
}
public class MyInteger implements MyInterface<Integer> {
// ...
}
// ...
MyInteger foo = new MyInteger();
// ...
List<Integer> list = foo.query();
// ...
Integer i = list.get(index);
Or with var, since it's been in the language a while now:
// ...
var foo = new MyInteger();
// ...
var list = foo.query();
// ...
var i = list.get(index);
So does it make sense to use interface here, or better to implement two separate class with same method signature without common interface ?
That depends. If you will have several classes that will implement MyInterface<Integer> and you need to deal with instances of those classes in a common way (e.g., so you refer to them with MyInterface<Integer> rather than the class) and/or if MyInterface represents some basic aspect of your overall structure, then probably it makes sense to use an interface. If you don't, if it's just that you're going to have two different classes with List<something> query methods, it may not. It depends on the overall design and (a bit) on style.
I have an abstract class in my application (let's call it BaseRule).
BaseRule implements the Comparable interface, and contains an abstract method signature public abstract int getExecOrder().
Within the BaseRule implementation of the compareTo() method in the BaseRule class, the return value of getExecOrder() is used to compare the objects.
At present, I have 3 concrete implementations of the BaseRule class, each of which implement the getExecOrder() method
The ultimate purpose of having the BaseRule class implement the Comparable interface is that a Collection of BaseRule objects are passed to a utility that needs to sort these objects to ensure that they are executed in the proper order.
In this case, execution order only matters at the Class level, meaning that every BaseRuleA must be executed before any BaseRuleB is executed, but every BaseRuleB is effectively 'equal' to every other BaseRuleB, so the order that those BaseRuleB objects are processed does not matter
My question is, is there a better way to handle comparing these objects as opposed to using (what I came up with) a getExecOrder() method ?
Right now, I only have 3 concrete implementations of BaseRule so it was easy enough to just assign return values of 1,2,3 to those getExecOrder() method calls, but if another developer adds a new BaseRule implementation, they would have to scan all the existing implementations, and (possibly) update those return values in all of the classes to accommodate the new BaseRule.
Any ideas on a better implementation?
I guess you're talking about the following sort of thing?
abstract class BaseRule implements Comparable<BaseRule>
{
abstract int executionPrecedence();
#Override
public int compareTo(final BaseRule that)
{
return Integer.compare(this.executionPrecedence(), that.executionPrecedence());
}
}
class RuleA extends BaseRule
{
#Override
int executionPrecedence() { return 0; }
}
class RuleB extends BaseRule
{
#Override
int executionPrecedence() { return 1; }
}
It seems fairly reasonable. If you're concerned about having to change the values of existing classes in the future then just leave big gaps rather than using contiguous integers.
A = 10000
B = 20000
C = 30000
Now you have 9999 spaces to place future implementations between these ones.
Maybe also add a unit test which uses reflection to check that no two implementations share the same precedence.
I honestly think your proposed implementation is the best way to go about this. Definitely add some comments to the abstract getExecOrder() so that future developers know exactly what their implementation of it is supposed to do.
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.
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.