Should 'Comparable<T>' be a 'Functional interface'? - java

The definition of a functional interface is "A functional interface is an interface that has just one abstract method
(aside from the methods of Object ), and thus represents a single function contract."
According to this definition, the Comparable<T> is definitely a functional interface.
The definition of a lambda expression is "A lambda expression is like a method: it provides a list of formal parameters
and a body - an expression or block - expressed in terms of those parameters."
Evaluation of a lambda expression produces an instance of a functional interface.
Thus, the purpose of the lambda expression is to be able to create an instance of the functional interface, by implementing
the single function of the functional interface. ie. to allow the creation of an instance with the single function.
Let us look at Comparable<T>, is this interface designed for use as a single function?
ie. was it designed for the creation of instances with this single function only?
The documentation of Comparable<T> starts with "This interface imposes a total ordering on the objects of each class that
implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred
to as its natural comparison method."
The above sentence makes it clear that the Comparable<T> is not designed to be used as a single function, but is always
meant to be implemented by a class, which has natural ordering for its instances, by adding this single function.
Which would mean that it is not designed to be created by using a lambda expression?
The point is that we would not have any object which is just Comparable only, it is meant to be implemented and thus used
as an additional function for a class.
So, is there a way in the Java language, by which creation of a lambda expression for Comparable<T> is prevented?
Can the designer of an interface decide that this interface is meant to be implemented by a class and not meant to be
created as an instance with this single method by use of a lambda expression?
Simply because an interface happens to have a single abstract method, it should not be considered as a functional interface.
Maybe, if Java provides an annotation like NotFunctional, it can be checked by the compiler that this interface is not used
for the creation of a lambda expression, eg.
#NotFunctional
public interface Comparable<T> { public int compareTo(T t); }

A lambda expression can be used where an instance of an interface with a single abstract method is required. You wrote,
Simply because an interface happens to have single abstract method, it should not be considered as a functional interface.
This is exactly correct. Having a single abstract method is a structural property of an interface, one that makes it eligible to be implemented with a lambda. However, whether an interface makes sense or is semantically sensible to be implemented with lambda is a different story. The latter is the purpose of the #FunctionalInterface annotation. When it is present on an interface, it indicates the intent that the interface is useful to be implemented with a lambda.
Notably, the Comparable interface lacks the #FunctionalInterface annotation.
While it's probably nonsensical to use a lambda as a Comparable implementation, there doesn't seem to be any reason to create a mechanism to prevent this from being done. It doesn't seem like doing this would be a source of error, which would be a good reason to develop such a mechanism. By contrast, the #FunctionalInterface annotation is intended to guide programmers in the right direction instead of prohibiting something that is arguably wrong but doesn't seem truly harmful.

The issue comes from a subtle difference between a "method" and a "function".
The output value of a function depends ONLY on the arguments that are input to that function.
However the output of a method depends on the arguments that are input to the function but it may also depend on the object's state (instance variables).
That is, any function is a method but not all methods are functions.
For example, the method compare in the interface Comparator depends only on its arguments. However, the method compareTo in the interface Comparable depends on the state of the object to compare to, so it needs to be implemented in a class.
So even Comparable has one abstarct method, semantically it shouldn't be considered as a functional interface.

Well, asides from the discussion how usefull the informative annotation #FunctionalInterface is (and I am happy Java 8 does not require it for lambdas).
Comparable is typically a property of a type and therefore not a good candidate for a functional interface. It is explicitly described as the natural ordering and does not take the two this/that arguments. So this property makes it unlikely any method would operate on a lambda (similliar argument is applicable for nearly all -able interfaces).
So, the collection designers use a second interface for that task: Comparator<T>, and for that a lambda implementing it is a very natural choice.

There is no mechanism to prevent a naive use of an interface not intended to be a functional interface.
by having an additional annotation like #NotFunctional, it could be declared explicitly by a
designer of an interface, that it should not be used as lambda.
And by default if no annotation is specified, it can be considered as good as #Functional,
which is currently the case.

Related

Functional programming, objects that act as functions but don't return a value

I am trying to do some functional programming with java.
Function Objects takes one value and returns one value. Method takes no arguments.
Is there a default Object which takes one argument and returns nothings? Or should I create my own?
NewObject<String> stopListAdd =
line -> stopList.add(xxx);
If I were to construct my own is there any way better than extending the Function object and just dismissing its return value?
Sure, java uses functional interfaces to back the type behind lambdas. In short, when creating a lambda you are just implementing an interface with a single abstract method, called a functional interface. So if you want to create your functional types, you just need to create an interface with a single abstract method that matches your requirements, like in this case
void accept();
One side note, default methods can be added to a functional interface as they are in fact implemented already.
So, Function and other similar types are not the full extents of functional types in java, but rather a subset of commonly used, reusable and well-known functional interfaces that you don't have to redeclare each and every time.
java.util.function.Consumer accepts a single input argument and returns no result.

Why doesn't java.lang.ref.Reference<T> implement Supplier<T>?

I'm looking at the class java.lang.ref.Reference (and it's sub-classes) and I'm wondering why it doesn't implement Java 8's Supplier<T> interface.
Seems like this should be a no-brainer. Supplier's get() method is satisfied by Reference. The only reason I'm hesitating to implement an extension of SoftReference<T> myself that also implements Supplier<T> is because I know that References are special-cased by the garbage collector.
Are there any problems you can forsee with making a class like this
public class SoftReferenceSupplier<T> extends SoftReference<T> implements Supplier<T>
{
public SoftReferenceSupplier(T referent)
{
super(referent);
}
public SoftReferenceSupplier<T referent, ReferenceQueue<? super T> queue)
{
super(referent,queue);
}
}
I don't want to in some way defeat the purpose of SoftReferences because of some garbage collection caveats interferring with how Supplier's are handled.
BTW, I am aware the SoftReferences will return null upon a full garbage collection. I have a need SoftReferences in my program and I'd like to have it implement this function interface in order to increase the flexibility.
Reference is a lot older than Supplier. As far as I can tell, changing Reference<T> to implement Supplier<T> would not have broken any existing code, however in my view it wouldn't make a lot of sense. When all the new functional interfaces were introduced into the language, it would have been possible to have gone through every existing class and make each one implement every new functional interface that happened to have a matching method, but I can't see the value of this.
In many cases, there is no point in a class actually implementing a functional interface at all, because if you need to regard an object as an instance of a functional interface, you can just use a method reference.
Reference<Object> reference = new WeakReference<>(someObject);
Supplier<Object> supplier = reference::get;
This solution does not depend on the fact that the two methods happen to both be called get, so in my view it is preferable to making Reference implement Supplier.
I did some Googling, but didn't find anything related to why Java's Reference class doesn't implement the Supplier interface. But the Javadoc of Supplier leaves some clues. I think that the answer lies in how the Supplier was introduced to Java - namely as a functional programming interface for use in Lambda expressions. The meanings of the two get() methods just mean logically different things. The get() method of an instance of the Reference class returns the referent; the get() method of Supplier instance returns the result of a lambda expression. It's hard to imagine a semantic overlap between the two, unless I was creating a lambda expression involving JVM soft, weak, and/or phantom references.

Why isn't #FunctionalInterface used on all the interfaces in the JDK that qualify?

Java 8 gave us many fun ways to use functional interfaces and with them a new annotation: #FunctionalInterface. Its job is to tell the compiler to yell at us if we fail to stick to the rules of a functional interface (only one abstract method that needs overriding please).
There are 43 interfaces in the java.util.function package with this annotation. A search of jdk.1.8.0/src for #FunctionalInterface only turns up 57 hits. Why are the other interfaces (such as AutoCloseable) that could have added #FunctionalInterface still missing it?
There is a bit of a vague hint in the annotations documentation:
"An informative annotation type used to indicate that an interface type declaration is intended to be a functional interface"
Is there any good reason NOT to intend that an interface I've designed (that may simply happen to be a functional interface) not be used as one? Is leaving it off an indication of anything besides not realizing it could have been added?
Isn't adding abstract methods to any published interface going to screw anyone implementing it, functional or not? I feel cynical assuming they just didn't bother to hunt them all down but what other explanation is there?
Update: After looking over "Should 'Comparable' be a 'Functional interface'?" I find I still have nagging questions. When a Single Method Interface and a Functional Interface are structurally identical what's left to be different? Is the difference simply the names? Comparable and Comparator are close enough to the same semantically. Turns out they are different structurally though so still not the best example...
Is there a case when an SMI is structurally fine to use as a Functional Interface but still discouraged over the semantic meaning of the name of the interface and the method? Or perhaps the contract implied by the Javadocs?
Well, an annotation documenting an intention would be useless if you assume that there is always that intention given.
You named the example AutoCloseable which is obviously not intended to be implemented as a function as there’s Runnable which is much more convenient for a function with a ()->void signature. It’s intended that a class implementing AutoCloseable manages an external resource which anonymous classes implemented via lambda expression don’t do.
A clearer example is Comparable, an interface not only not intended to be implemented as a lambda expression, it’s impossible to implement it correctly using a lambda expression.
Possible reasons for not marking an interface with #FunctionalInterface by example:
The interface has programming language semantics, e.g. AutoClosable or Iterable (that’s unlikely to happen for your own interfaces)
It’s not expected that the interface has arbitrary implementations and/or is more an identifier than the actual implementation, e.g. java.net.ProtocolFamily, or java.lang.reflect.GenericArrayType (Note that the latter would also inherit a default implementation for getTypeName() being useless for lambda implementations as relying on toString())
The instances of this interface should have an identity, e.g. java.net.ProtocolFamily, java.nio.file.WatchEvent.Modifier, etc. Note that these are typically implemented by an enum
Another example is java.time.chrono.Era which happens to have only a single abstract method but its specification says “Instances of Era may be compared using the == operator.”
The interface is intended to alter the behavior of an operation for which an implementation of the interface without inheriting/implementing anything else makes no sense, e.g. java.rmi.server.Unreferenced
It’s an abstraction of common operations of classes which should have more than just these operations, e.g. java.io.Closeable, java.io.Flushable, java.lang.Readable
The expected inheritance is part of the contract and forbids lambda expression implementations, e.g. in java.awt: ActiveEvent should be implemented by an AWTEvent, PrinterGraphics by a Graphics, the same applies to java.awt.print.PrinterGraphics (hey, two interfaces for exactly the same thing…), wheras javax.print.FlavorException should be implemented by a javax.print.PrintException subclass
I don’t know whether the various event listener interfaces aren’t marked with #FunctionalInterface for symmetry with other multi-method event listener that can’t be functional interfaces, but actually event listeners are good candidates for lambda expressions. If you want remove a listener at a later time, you have to store the instance but that’s not different to, e.g. inner class listener implementations.
The library maintainer has a large codebase with more than 200 candidate types and not the resources to discuss for every interface whether it should be annotated and hence focuses on the primary candidates for being used in a functional context. I’m sure, that, e.g. java.io.ObjectInputValidation, java.lang.reflect.InvocationHandler, juc RejectedExecutionHandler & ThreadFactory wouldn’t be bad as #FunctionalInterface but I have no idea whether, e.g. java.security.spec.ECField makes a good candidate. The more general the library is, the more likely users of the library will be able to answer that question for a particular interface they are interested in but it would be unfair to insist on the library maintainer to answer it for all interfaces.
In this context it makes more sense to see the presence of a #FunctionalInterface as a message that an interface is definitely intended to be usable together with lambda expressions than to treat the absence of the annotation as an indicator for it’s being not intended to be used this way. This is exactly like the compiler handles it, you can implement every single abstract method interface using a lambda expression, but when the annotation is present it will ensure that you can use this interface in this way.
Planned expansion. Just because an interface matches the requirements of an SMI now doesn't mean that expansion isn't needed later.
In java 8, functional interface is an interface having exactly one abstract method called functional method to which the lambda expression’s parameter and return types are matched.
The java.util.function contains general purpose functional interfaces used by JDK and also available for end users. While they are not the complete set of funtional interfaces to which lambda expressions might be applicable, but they provide enough to cover common requirements. You are free to create your own functional interfaces whenever existing set are not enough.
There are many such interfaces available which deserves to be designated as functional interface but java.util.function package already provides functional interfaces for our almost all purposes.
For example look into following code.
public interface Comparable<T> {
public int compareTo(T o);
}
#FunctionalInterface
public interface ToIntFunction<T> {
int applyAsInt(T value);
}
public static void main(String[] args){
ToIntFunction<String> f = str -> Integer.parseInt(str);
Comparable<String> c = str -> Integer.parseInt(str);
}
Comparable can also take an object and derive some int type value but there is a more general dedicated interface ToIntFunction is provided to perform this task. There is no such hard rule that all the deserving interfaces should be annotated with #FunctionalInterface but to gain the advantage of lambda feature, the interface should fulfill all criterias defined by FunctionalInterface.

About the Java interface and polymorphism

I just met an strange case when reading the Java doc. Here is the link to Oracle's java doc on Arrays.asList method, http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#asList(T...)
There is an example in the doc
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
My question is, as List is an interface, why can we declare stooges as a 'List', rather than a concrete subclass implementing List(e.g. ArrayList or LinkedList)?
So does it mean that we can have a reference variable of interface type? It looks quit weird to me as I always think that interface stands only for polymorphism, and we should never really use a interface type variable.
Could anyone please give me some clue on this?
Think of the List interface as a guarantee. Any class that implements List will be guaranteed to have the methods of the interface. When Arrays.asList() returns a List you're not actually getting an interface, you're getting a concrete class that is guaranteed to implement the methods listed in the List interface.
As to your "we should never really use a interface type variable" you're actually suppose to do that. It's called "programming to the interface". It's much more flexible if you can return a List as opposed to something like a LinkedList. The caller of your method isn't coupled to your specific implementation internal implementation which might use, and return, a LinkedList. If at some point you wanted to return a ArrayList instead of the LinkedList the caller would not have to change any code because they only care about the interface.
What does it mean to "program to an interface"?
Just a word of note, Serializable is a marker interface and a little odd because of that. It doesn't guarantee that methods are there, but instead guarantees that the creator of the class that implements serializable has thought about the many issues associated with serializing a class (overriding readObject/writeObject, compatiblity with other serialized forms, and other issues http://www.javapractices.com/topic/TopicAction.do?Id=45). So Serializable is still offering a guarantee, like List is, but it isn't about method signatures, it's about an extralinguistic feature of the language.
http://en.wikipedia.org/wiki/Marker_interface_pattern
Using an Interface as a reference type is a perfectly valid practice in Java. For example, the Serializable interface will do this inside it's class, so that any object that is passed to it can be serialized.
This is also how Java provides something that resembles Multiple Inheritance. For example:
public interface A { }
public class B implements A {}
public class program {
B bClass = new B();
A aObject = (A)bClass;
}
That way the same object can be referenced with different reference types, and all without messing up an inheritance chain!
The interface defines a contract or a specification for an implementation. Which is the methods and their signature. So a class that implements an interface has to respect that contract. This way you can change implementation without affecting the code that uses interfaces for declaring variables.
In the example you mentioned:
You don't know what implementation of the List interface Arrays.asList is using unless you look into the code. So how would you know which one to use? (see javadoc for list interface to see what implementations it has)
The implementation is subject for change, what if Arrays.asList decides to use another implementation? Your code will be broken.
The signature of the method Arrays.asList is that it returns List<T> so if you want to have a concrete implementation as variable you'll have to cast that return value which is bad practice or to create new - let's say ArrayList - and copy all the elements into it, which is just an unnecessary overhead.
Effective Java by Bloch is a great book on Java best practices. In particular, item #52 talks about this: "If the appropriate interface types exist ... declared using the interface types."
The general notion is that, for greatest flexibility and understandability, you should use the type that best reflects the context, which is usually the interface. In the example, you provided, does the exact implementation matter or just that it is a List. Of course, if the code requires an ArrayList-specific method or if the code is relies on an ArrayList-specific behavior, then use the concrete class.
There are occasional exceptions, such as when using GWT-RPC, but this is for implementation reasons.
This is really good example of polymorphism power, if you like you can look at the source code of Arrays.asList() here Arrays.asList(T...a) ,you will find that it takes varibale length input and defines its own private static concrete class ArrayList that implements List interface rather than using the well known java.util.ArrayList or other java Collection type,
this may be to make it more efficient or something, you want to implement your own class and you return it to the user without overwhelming him by implementation details since there is an interface he can deal with your private class through.

What does "contract" of a class mean

I am reading the book The Java Programming Language. In the chapter which explains overriding method, it says:
Making an override method (in subclass) less accessible than it was in super class would violate the contract of the superclass ...
The text as a whole is understandable. My only question is what is contract of the superclass? What does the contract mean for a Java class?
A contract in in a Java class is similar to a contract in the real world - In non-technical terms:
It's an agreement that the class will expose certain methods, certain properties, and certain behaviors.
More technical, from here: (bold added by me)
Wouldn't it be nice if all Java classes that you use, including your
own, lived up to their promises? In fact, wouldn't it be nice if you
actually knew exactly what a given class promises? If you agree, read
on [...]
Design by Contract
The Design by Contract (DBC) software development technique ensures
high-quality software by guaranteeing that every component of a system
lives up to its expectations. As a developer using DBC, you specify
component contracts as part of the component's interface. The contract
specifies what that component expects of clients and what clients can
expect of it.
Contract of type (class, interface, enum) is the, well, the contract this type promises to comply to. It states:
what are acceptable parameters to constructor and/or methods of this type;
what you should and/or should not expect this type to be doing. For example, it may state that you shall expect this class to be thread-safe or not thread-safe;
what are invariants supported by this type. For example, type method addData(float) of MathAverage class which calculates average of its input may state that every time that your call to add(float) returns, you shall expect call to MathAverage.getAverage() to return correct average of current input.
generally speaking, your type can specify any constraint all it's subtypes must follow. For example, it may say "no method of this type must take longer than 1 second to execute".
Contract is specified in free-form in javadoc of type. There are some tools/practices to enforce execution of contracts, but they are limited, exactly because contract can be arbitrary, or, even, self-contradictory, in case of programmer's error.
Since subtyping(subclassing) can extend/modify behavior of supertype methods in arbitrary way, it may, as well, violate some parts of supertype's contract. Example of this would be extending HashMap, which accepts null values and keys, with some implementation which prohibits null values in calls to it's methods.
Other important aspect about type contract is that subtype can have stronger contract (covering subset of constraints in type's contract), but can't have weaker contract (covering superset of constraints in type's contract).
For example, if your type's method 'doX(n)' promises to take O(n) (linear) time, 'doX(n)' in subtype can take O(1) (constant) time, but can not take O(n^2) time.
It means that method overriding a method on a parent class or interface must behave in the way that the contract defines.
Otherwise the result is undefined.
A class's "Contract" is it's public interface or at least the interface if presents to classes other than itself.
This means that it includes any elements (methods, fields, constructors, etc.) that other classes can use.
The contract of a class or interface, in Java or any other OO language, generally refers to the publicly exposed methods (or functions) and properties (or fields or attributes) of that class interface along with any comments or documentation that apply to those public methods and properties.
In the case of the relationship between a class and subclass, any protected methods or properties would be considered "publicly exposed," in the sense that they are exposed to the subclass.
There is many principles that you should conform to when programming in java, or in any programming languages. The principles depend on the programming language you are using. You can know more about contract in Design by contract wikipedia page
in simple terms it means you would break the conditions of superclass if u make override code less accesible
It's an expression that comes from the idea of contracts in the "real world."
Basically, if you break your contract with a class, then it's not required to behave the way you might expect. From the other direction, it's a promise by the class that if you follow the rules it sets out, it will behave the way its API says.
One common example of a contract in Java is overriding equals() when hashCode() is overridden. Two objects that are considered equal must, by contract, have the same hash code. It's possible to write code that's syntactically correct that doesn't obey this, but it might not work properly, and that's the fault of the programmer who broke the contract.

Categories

Resources