Are sub-interfaces the solution to default-method conflicts? - java

Consider the following code, which is an extraction of a real use case where LinkedList<E> implements both List<E> and Deque<E>.
One can observe that both interfaces have a size() and an isEmpty() method, where the isEmpty() method could be made default in terms of size().
So, let's do that (with dummy interfaces), since Java 8 does not do it yet:
interface List<E> {
public int size();
default public boolean isEmpty() {
return (size() == 0);
}
//more list operations
}
interface Deque<E> {
public int size();
default public boolean isEmpty() {
return (size() == 0);
}
//more deque operations
}
class LinkedList<E> implements List<E>, Deque<E> {
private int size;
#Override
public int size() {
return size;
}
}
Oops! We get a compile-time error on LinkedList, as it does not know which isEmpty() implementation to use, so we add this:
#Override
public boolean isEmpty() {
return List.super.isEmpty();
}
Now we have lost practically all benefits of default methods for this use case, as it still takes us as much code to write the isEmpty() method as it did before.
But can it be solved? Yes!
Consider the following implementation:
interface Sizable {
public int size();
default public boolean isEmpty() {
return (size() == 0);
}
}
interface List<E> extends Sizable {
//list operations
}
interface Deque<E> extends Sizable {
//deque operations
}
class LinkedList<E> implements List<E>, Deque<E> {
private int size;
#Override
public int size() {
return size;
}
}
So the question:
Is this how we, and also the JDK, are supposed to handle it in future implementations?

I strongly discourage from adding super-interfaces for unrelated interfaces just for defining default methods. Normally, you don’t have that problem as either, the interfaces are related like in your example so that a natural super-interface like Collection exists or could be defined for more than just providing default methods. Or they are really unrelated and a class implementing both is either unlikely or will have to define which semantics to inherit, anyway.
In case of the Collection API having no default method for isEmpty is intentional as size can be an expensive operation for some Collections. If your Collection shares behavior with typical Collections you may inherit from AbstractCollection.

Related

this keyword doesn't represent an object

Does anyone know why can we loop through the "this" keyword here (in the subsetOf method)? To my knowledge this represents a JAVA object. Some extensive explanations are welcomed, would like to know why "this" can work in this way.
public class ArrayListSet<E> implements Set<E> {
private ArrayList<E> elements;
public ArrayListSet() {
elements = new ArrayList<>();
}
#Override
public void add(E e) {
if (!elements.contains(e))
elements.add(e);
}
#Override
public void remove(E e) {
elements.remove(e);
}
#Override
public boolean contains(Object e) {
return elements.contains(e);
}
#Override
public int size() {
return elements.size();
}
#Override
public boolean subsetOf(Set<?> other) {
for (E e : this) {
if (!other.contains(e))
return false;
}
return true;
}
}
You are declaring a class which implements the Set interface which itself extends the Iterable through the Collection interface. Any Object which is an implementation of the Iterable interface can be used inside a for-each loop.
So the inheritance hierarchy is this for your class:
Iterable
^
|
Collection
^
|
Set
^
|
ArrayListSet
Also the this keyword always refers to the current instance. In your code when you execute the subsetOf() the this will point to an instance of ArrayListSet (which was used to invoke the subSetOf() method) which is a type of Iterable through inheritance, so you can use it in a for-each loop.
Also since you are implementing a Set you need to supply an implementation of the Iterator<E> iterator(); method defined in the Set interface to make it an Iterable.
As implementations of the Iterable interface requires a iterator() method which returns an instance of the Iterator object. The Iterator Object will be used by the for-each loop to iterate over the elements of the ArrayListSet.
The implementation of the Iterator type returned from the iterator() method actually defines the iteration logic used by the for-each loop.
To use any Object in a for-each loop:
Step 1: Extend Iterable directly or through other Iterable types.
Step 2: Provide implementation of the Iterator iterator() method inherited from the Iterable interface.
Step 3: Implement an Iterator and return its instance from the iterator() method.
You can iterate through this since it represents a set. The set is iterable. Therefore it is valid syntax.

Are there scenarios in which "Down casting" Collection<? extends T> to Collection<T> makes sense

The stackoverflow question: Is List<Dog> a subclass of List<Animal>? Why aren't Java's generics implicitly polymorphic? has many correct answers that point out that you can add a Cat to List<Animal> but not to List<Dog>. This leads to the use of constructs like List<? extends Animal>. I have found that there are cases where this is just not convenient and therefore I have defined classes to "down cast" the collection. (See below for an example of DownCastCollection). My question is whether you can present some cases where the best approach is to downcast? If you think it is never the best approach then can you explain why? I realize this is a bit open ended but I think the answers may be very helpful since this situation is common. I do agree that in most cases we should use the `Collection, but I am pointing out that sometimes that is just not the best approach. Have you encountered examples where this is not the best approach and if so can you present them here?
Based on the answer in https://stackoverflow.com/a/27491199/4350148 i have changed DownCastCollection to be modifiable and so now it does not return an error. The question still is valid.
Here is the downcast collection class:
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class DownCastCollection<E> extends AbstractCollection<E> implements Collection<E> {
#SuppressWarnings("rawtypes")
private Collection delegate;
public DownCastCollection(Collection<? extends E> delegate) {
if(delegate == null) throw new IllegalArgumentException();
this.delegate = delegate;
}
#Override
public int size() {
return delegate.size();
}
#Override
public boolean isEmpty() {
return delegate.isEmpty();
}
#Override
public boolean contains(Object o) {
return delegate.contains(o);
}
private class MyIterator implements Iterator<E>{
#SuppressWarnings("rawtypes")
Iterator delegateIterator;
protected MyIterator() {
super();
this.delegateIterator = delegate.iterator();
}
#Override
public boolean hasNext() {
return delegateIterator.hasNext();
}
#SuppressWarnings("unchecked")
#Override
public E next() {
return (E)delegateIterator.next();
}
#Override
public void remove() {
delegateIterator.remove();
}
}
#Override
public Iterator<E> iterator() {
return new MyIterator();
}
#SuppressWarnings("unchecked")
#Override
public boolean add(E e) {
return delegate.add(e);
}
#Override
public boolean remove(Object o) {
return delegate.remove(o);
}
#SuppressWarnings("unchecked")
#Override
public boolean containsAll(Collection<?> c) {
return delegate.containsAll(c);
}
#SuppressWarnings("unchecked")
#Override
public boolean addAll(Collection<? extends E> c) {
return delegate.addAll(c);
}
#SuppressWarnings("unchecked")
#Override
public boolean removeAll(Collection<?> c) {
return delegate.removeAll(c);
}
#SuppressWarnings("unchecked")
#Override
public boolean retainAll(Collection<?> c) {
return delegate.retainAll(c);
}
#Override
public void clear() {
if(delegate == null) return;
delegate.clear();
}
Collections.unmodifiableCollection and its friends are built-in ways to view a Collection<? extends T> as a Collection<T>. They resolve exactly the issue you have correctly identified, that elements can be added to a Collection<T> that cannot be added to a Collection<? extends T>, by forbidding additions or any sort of modification.
Other solutions to this problem include not depending on the implementation details of the underlying objects, forbidding addition but not removal, or making copies.
Finally, for what it's worth, your solution is exactly as type-safe, but less efficient, than simply casting your collection (Collection<E>) (Collection) collection, which takes advantage of erasure to simply (and unsafely) cast the backing collection.
With a collection of a generic type ? extends E, it is not legal to add new elements as the compiler cannot verify the exact type of the collection that your variable points to. Instead, the compiler can only tell that the collection represents any collection of subtypes of E. Thus:
Collection<? extends Something> collection = ...
collection.add(new Something());
does not compile. With your version of a DownCastCollection, the example would compile but instead throw a runtime exception. You migrate a compile-time error to become a runtime error. This is not a good idea as it introduces potential errors to your application that your compiler could otherwise catch.
The only reason when casting a generic collection makes sense would be when you for some reason know the actual type of the collection but you were not able to express this by your program's types. Better that a cast is normally to create a new collection:
Collection<? extends Something> collection = ...
Collection<Something> other = new HashSet<>(collection);
I usually use List<? extends T> if I have a superclass or interface that should allow its subclasses or implementations to specify the return value of a method more precisely.
Given you have the following interface.
public interface Foo {
public List<CharSequence> doSomething();
}
If you now want to create a class Bar implements Foo, the method signature of doSomething() will have to be List<CharSequence> doSomething() and nothing else.
However, if you define doSomething() like this...
public interface Foo {
public List<? extends CharSequence> doSomething();
}
Bar's doSomething() might have a method signature that looks like this.
public class Bar implements Foo {
public List<String> doSomething() {
// ...
}
}
Besides that, you should also pay attention to what #raphw said, you can't add elements to a List<?> or List<? extends T>.
Here is a scenario where the DownCastCollection class is useful. Suppose I have an interface (lets call it IFace) that has a method that returns Collection<Result>. Suppose that Impl is an implementation of IFace. In order to compute the Collection of Results for the method, Impl uses a particular implementation of the Result interface, called ResultImpl and maintains a list of Collection<ResultImpl>. ResultImpl has methods that are not part of the interface and hence maintaining Collection<Result> in that method does not work without casting up. My implementation of the method needs to return Collection<Result> from the Collection<ResultImpl> and this is where the DownCastCollection is useful. You might argue that the method can return Collection<? extends Result> however, that would alter the interface IFace. In other words the method wants the guarantee that Collection<Result> is returned. We may also want to allow the caller of the method to modify the final result by adding to it or removing from it. In that case we still need the returned result to be modifiable.

Can ListIterator safely be susbtituted for Iterator? (Implementing a CopyOnWrite wrapper for List)

I have many instance in code where a Collection, most usually a List is returned from a method and to account for the caller possibly altering that list, a defensive copy is made.
The JDK does not seem to provide a wrapper for this purpose, so I'm trying to roll my own (Note: java.util.concurrent.CopyOnWriteArrayList is not what I'm looking for here).
Schematically, what I'm trying is:
public class CopyOnWriteList<E> extends List<E> {
protected List<E> list;
protected boolean isCopied;
public CopyOnWriteList(List<E> list) {
this.list = list;
}
private void ensureCopy() {
if (!isCopied) {
list = new ArrayList<E>(list);
isCopied = true;
}
}
public E get(int i) {
return list.get(i);
}
public boolean add(E e) {
ensureCopy();
return list.add(e);
}
// ... many more simple methods
}
For most of the API this is simple enough, but looking at java.util.ArrayList I found, that for the method iterator() it returns a different implementation than for listIterator(), although is ListIterator extends its Iterator and it doesn't add any new members.
I wonder if there is a deeper reason behind this - I planned simply to implement iterator() and listIterator() all returning the same type of iterator - a ListIterator. Is there any logical reason why one should not return a ListIterator from the iterator()-method?
ListIterator extends Iterator. So if you return an object that implements ListIterator then it obviously also implements Iterator. But you also can decide to return different object that only implements Iterator, because the implementation could be more effective. The decision is up to you.

converting Comparable from and to Comparator?

I often have a Comparator type while I need a Comparable and the other way around. Is there a reusable JDK API to convert from one another? Something along the lines of:
public static <C> Comparable<C> toComparable(final Comparator<C> comparator) {
// does not compile because Hidden can not extend C,
// but just to illustrate the idea
final class Hidden extends C implements Comparable<C> {
#Override
public int compareTo(C another) {
return comparator.compare((C) this, another);
}
};
return new Hidden();
}
public static <C extends Comparable<C>> Comparator<C> toComparator(final Class<C> comparableClass) {
return new Comparator<C>() {
#Override
public int compare(C first, C second) {
assert comparableClass.equals(first.getClass());
assert comparableClass.equals(second.getClass());
return first.compareTo(second);
}
};
}
ComparableComparator from Apache Commons Collections seems to address Comparable<T> to Comparator problem (unfortunately its not generic type-friendly).
The reverse operation is not quite possible because the Comparator<T> represents algorithm while Comparable<T> represents actual data. You will need composition of some sort. Quick and dirty solution:
class ComparableFromComparator<T> implements Comparable<T> {
private final Comparator<T> comparator;
private final T instance;
public ComparableFromComparator(Comparator<T> comparator, T instance) {
this.comparator = comparator;
this.instance = instance;
}
#Override
public int compareTo(T o) {
return comparator.compare(instance, o);
}
public T getInstance() {
return instance;
}
}
Say you have class Foo that is not Comparable<Foo> but you have Comparator<Foo>. You use it like this:
Comparable<Foo> comparable = new ComparableFromComparator<Foo>(foo, comparator);
As you can see (especially without mixins) it's pretty ugly (and I'm not even sure if it'll work...) Also notice that comparable doesn't extend Foo, you have to call .getInstance() instead.
Since Java 8 the Comparator interface has had a few utility default methods added that assist with deriving a comparator from a comparable.
Consider the following example of sorting users by first name.
class Person {
String firstName;
String lastName;
}
List<Person> people = ...
people.sort(Comparator.comparing(Person::firstName));
You can obtain an instance of Comparator able to compare instance of Comparable type simply with
java.util.Comparator.naturalOrder()
see Comparator.naturalOrder()
this is a sort of conversion from Comparable to Comparator
Comparable items can be sorted as they have a compareTo:
Collection<Comparable> items;
Collections.sort(items);
If items are not Comparable, they need a Comparator object to do the comparison:
Collections<T> items;
Collections.sort(items, comparator);
A bridging Comparator is trivial, and you did it already.
Wrapping every T item with some Comparable adapter having a Comparator, seems useless.
First of all not inheritance but as field one needs to wrap the item.
public class CatorComparable<T> implements Comparable<CatorComparable<T>> {
public T value;
private Comparator<T> cator;
public CatorComparable(T value, Comparator<T> cator) {
this.value = value;
this.cator = cator;
}
#Override
public int compareTo(CatorComparable<T> other) {
return cator.compareTo(value, other.value);
}
}
Too much overhead.
I don't think you can really convert between them, nor does it really make sense to, since Comarable is a property of the class itself, while Comparator is an external class.
The best bet would be to write some sort of utility class that contains the underlying comparison logic (and probably have that implement Comparator), then use that class as a part of the logic for the Comparable implementation on the class itself.

Java: Set<E> collection, where items are identified by its class

I need Set collection, where its items will be identified by items class. Something like ReferenceIdentityMap from Appache Collections, but on class scope i.e. two different instances of same class must be identified as same in this collection.
You know, it is a violation of equals()/hashCode() identity principle but in occasional use it makes sense.
I have done this in simple class backing with Map<Class<? extends E>, E>, but due to simplicity it doesn't implement Set<E>. There may be a more elegant solution, decorator of any Set<E> would be great.
Is there any implementation of such collection there (Apache/Google/something/... Collections)?
You wish to override the meaning of equals() / hashCode() for your set members. The cleanest way to do this, I imagine, is to use a wrapper class:
class Wrapper<E> {
private final E item;
Wrapper(E item) {
this.item = item;
}
E getItem() {
return item;
}
public boolean equals(Object o) {
if (!(o instanceof Wrapper)) {
return false;
}
return getClass().equals(o.getClass());
}
public int hashCode() {
return getClass().hashCode();
}
}
You would create a Set<Wrapper<E>> then.
How about extending HashSet and overriding just the add(..) method, putting object.getClass() instead of the object itself in an inner Set<Class<? extends E>>, and if it succeeds, adding the item itself. Something like
public class ClassSet<E> extends HashSet<E> {
private Set<Class<? extends E>> classSet = new HashSet<Class<? extends E>>();
#Override
public boolean add(E element) {
if (classSet.add((Class<E>) element.getClass())) {
return super.add(element); // this actually should always return true
}
return false;
}
}
You can create a Comparator class and construct your set with it in mind. The only condition you must not violate is that for every two elements you try to add, compare(e1, e2) should not throw a ClassCastException - which means that every two members you would try to insert should be comparable.
The comparator class itself should look only at the objects' classes, so it will be safe.
Check out the constructor here.

Categories