Make Java parent class not part of the interface - java

(This is a hypothetical question for discussion, I have no actual problem).
Say that I'm making an implementation of SortedSet by extending LinkedHashMap:
class LinkedHashSortedMapThing extends LinkedHashMap implements SortedSet {
...
}
Now programmers who use this class may do
LinkedHashMap x = new LinkedHashSortedMapThing();
But what if I consider the extending of LinkedHashMap an implementation detail, and do not want it to be a part of the class' contract? If people use the line above, I can no longer freely change this detail without worrying about breaking existing code.
Is there any way to prevent this sort of thing, other than favouring composition over inheritance (which is not always possible due to private/protected members)?

I think the easiest way would be to make a private inner class that extends LinkedHashMap, and have LinkedHashSortedMapThing keep a reference to that and point all its methods there.
class LinkedHashSortedMapthing implements SortedSet {
private class Foo extends LinkedHashMap {
...
}
private Foo foo;
public void clear() {foo.clear();}
public boolean containsValue(Object value) {return foo.containsValue(value);}
...
}

If you extend a class, you inherit its public interface and there is no way to avoid this AFAIK. Composition would be the favourable solution indeed, as you are not supposed to depend on the internals of LinkedHashMap anyway - these can also change in future JDK versions.
Java has no private inheritance as C++ do (which is practically more or less equivalent to composition anyway).

You can implement SortedSet by aggregation, so that the public interface of the class does not include LinkedListHashMap
class LinkedHashSortedMapThing extends AbstractSet implemenents SortedSet
{
LinkedListHashMap map;
public int size() {
return map.size();
}
}

First, the code should declare the variable with the interface Set or SortedSet. But you can hide the implementation by Not inheriting from LinkedHashMap. Just implement the interface and delegate to a LinkedHashMap member.
If you need protected access to LinkedHashMap functionality, use a private inner class as the delegation member.

Related

Force client to provide implementation of an innerclass when extending an outerclass

I was wondering if it is possible to force clients to provide an implementation of an innerclass when they define a new implementation of the outerclass.
To explain the situation better: I've an abstract class
public abstract class ImmutablePolynomial implements Iterable {
protected int degree;
static ImmutablePolynomial sum(ImmutablePolynomial x, ImmutablePolynomial y) {
.... Some Implementation using an iterator over terms and a return statement....
}
public abstract TermIterator iterator();
Here I want an innerclass (TermIterator) extending Iterator that must be implemented
if you extend ImmutablePolynomial.
Now the client can provide an implementation of an ImmutablePolynomial, using a specific datastructure to for example reduce memory usage, by extending this class.
How can I force the client to also provide an implementation of an Innerclass Implementing Iterator such that the static method sum in ImmutablePolynomial also works with the implementation provided by the client?
Also if this is a bad idea / antipattern / there is a better alternative please tell me so. I'm doing this to improve my coding.
Edit 1: remove the field
protected Collection terms
, as is adviced in the comments.
Edit 2: make method
iterator()
abstract as is adviced in the comments
Given that the ImmutablePolynomial class is abstract, so that you will never have an object whose class is ImmutablePolynomial, and given you don't want instances of ImmutablePolynomial's subclasses to use class ImmutablePolynomial.TermIterator, when would ImmutablePolynomial.TermIterator ever be used? It is pointless to implement it as an inner class.
As #Tassos suggested in comments, declare TermIterator as an interface instead; this may be nested in class ImmutablePolynomial or not, as you prefer. Also make ImmutablePolynomial.iterator() abstract.
To the extent that you have any concrete methods in ImmutablePolynomial that rely on the iterator, implement them against the interface instead of against any particular implementation. That's the only sane approach anyway when you not only allow but require subclasses to supply their own implementation.

How to subclass Guava's ImmutableList?

When I try to implement my own ImmutableList (actually a wrapper that delegates to the underlying list) I get the following compiler error:
ImmutableListWrapper is not abstract and does not override abstract method isPartialView() in com.google.common.collect.ImmutableCollection
But in fact, it seems to be impossible to override isPartialView() because it is package protected and I'd like to declare the wrapper in my own package.
Why don't I simply extend ImmutableCollection? Because I want ImmutableList.copyOf() to return my instance without making a defensive copy.
The only approach I can think of is declaring a subclass in guava's package which changes isPartialView() from package-protected to public, and then having my wrapper extend that. Is there a cleaner way?
What I am trying to do
I am attempting to fix https://github.com/google/guava/issues/2029 by creating a wrapper that would delegate to the underlying ImmutableList for all methods except spliterator(), which would it override.
I am working under the assumption that users may define variables of type ImmutableList and expect the the wrapper to be a drop-in replacement (i.e. it isn't enough to implement List, they are expecting an ImmutableList).
If you want your own immutable list but don't want to implement it, just use a ForwardingList. Also, to actually make a copy, use Iterator as parameter for the copyOf. Here's a solution that should fulfill all your requirements described in the question and your answer.
public final class MyVeryOwnImmutableList<T> extends ForwardingList<T> {
public static <T> MyVeryOwnImmutableList<T> copyOf(List<T> list) {
// Iterator forces a real copy. List or Iterable doesn't.
return new MyVeryOwnImmutableList<T>(list.iterator());
}
private final ImmutableList<T> delegate;
private MyVeryOwnImmutableList(Iterator<T> it) {
this.delegate = ImmutableList.copyOf(it);
}
#Override
protected List<T> delegate()
{
return delegate;
}
}
If you want different behavior than ImmutableList.copyOf() provides, simply define a different method, e.g.
public class MyList {
public static List<E> copyOf(Iterable<E> iter) {
if (iter instanceof MyList) {
return (List<E>)iter;
return ImmutableList.copyOf(iter);
}
}
Guava's immutable classes provide a number of guarantees and make a number of assumptions about how their implementations work. These would be violated if other authors could implement their own classes that extend Guava's immutable types. Even if you correctly implemented your class to work with these guarantees and assumptions, there's nothing stopping these implementation details from changing in a future release, at which point your code could break in strange or undetectable ways.
Please do not attempt to implement anything in Guava's Imutable* heirarchy; you're only shooting yourself in the foot.
If you have a legitimate use case, file a feature request and describe what you need, maybe it'll get incorporated. Otherwise, just write your wrappers in a different package and provide your own methods and guarantees. There's nothing forcing you, for instance, to use ImmutableList.copyOf(). If you need different behavior, just write your own method.
Upon digging further, it looks like this limitation is by design:
Quoting
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableList.html:
Note: Although this class is not final, it cannot be subclassed as it has no public or protected constructors. Thus, instances of this type are guaranteed to be immutable.
So it seems I need to create my wrapper in the guava package.

Why should we declare an interface inside a class?

Why should we declare an interface inside a class in Java?
For example:
public class GenericModelLinker implements IModelLinker {
private static final Logger LOG =LoggerFactory.getLogger(GenericModelLinker.class);
private String joinAsPropertyField;
private boolean joinAsListEntry;
private boolean clearList;
private List<Link> joins;
//instead of a scalar property
private String uniqueProperty;
public interface Link {
Object getProperty(IAdaptable n);
void setProperty(IAdaptable n, Object value);
}
}
When you want to gather some fields in an object in order to emphasize a concept, you could either create an external class, or an internal (called either nested (static ones) or inner).
If you want to emphasize the fact that this cooperative class makes strictly no sense (has no use) outside the original object use, you could make it nested/inner.
Thus, when dealing with some hierarchy, you can describe a "nested" interface, which will be implemented by the wrapping class's subclasses.
In the JDK, the most significant example would be Map.Entry inner interface, defined within Map interface and implemented by various ways by HashMap, LinkedHashMap etc...
And of course, Map.Entry needed to be declared as public in order to be accessible while iterating the map wherever the code is.
If the interface definition is small and the interface will only be used by clients of the class it's defined in, it's a good way to organize the code. Otherwise, the interface should be defined in its own file.
This is inner interface. Java programming language allows defining inner classes and interfaces. This is typically useful if you want to limit visibility of this class or interface by scope of current outer class.
Some people use this mechanism for creating a kind of namespace. IMHO this is abuse of the language feature (in most cases).
To encapsulate behavior in a generic and resuable way.
Apart from nice example of Map.Entry used by Map implementation classes another good example is implementation of Strategy Pattern, where a execution strategy is evaluated and applied internally.
class Test
{
..
interface Cipher {
doAction();
}
class RAMPCipher implements Cipher{}
class DiskCipher implements Cipher{}
..
}
Inside your class you may need multiple implementations of an interface, which is only relevant to this particular class. In that case make it an inner interface, rather than a public / package-private one.
Only an interface inside a class can be declared private or protected. Sometimes, that makes sense, when the interface is only appropriate for use inside the outer class (or its subclasses).

Writing class that is subclass of Vector, java

Just hoping I could get someone to tell me I am doing this right or not, as I have never written something like this before. So I have to write a class named ProcessQueue that is a subclass of Vector, as well as a constructor that will define an empty queue. Also the Vector will be holding items of type "Object." So here it is...
public class ProcessQueue<Vector>{
ProcessQueue(){}
}
Not, that's not right. That's generic, not extending.
Besides, it's not a good idea. Your ProcessQueue might have a collection of some sort underneath, but it need not extend. Prefer composition to inheritance.
If you must implement something, start by having an API that actually looks like a Queue. There's a certain behavior that's expected; make sure that yours conforms to it. The best way is to implement an interface that enforces it.
public class ProcessQueue<T> implements Queue<T> {
// Have a private collection of some sort that provides the behavior that the interface requires
}
You're not extending Vector anywhere. Change your code to:
public class ProcessQueue<T> extends Vector<T> {
}
By the way, I don't recommend you using Vector at all. Check Why is Java Vector class considered obsolete or deprecated?. IMO if you have to do this it would be better extending ArrayList.
public class ProcessQueue<T> extends ArrayList<T> {
}
And in your code use a List:
List<SomeClass> lstQueue = new ProcessQueue<SomeClass>();
U̶n̶r̶e̶l̶a̶t̶e̶d̶ ̶t̶o̶ ̶t̶h̶e̶ ̶o̶r̶i̶g̶i̶n̶a̶l̶ ̶q̶u̶e̶s̶t̶i̶o̶n̶ , I think similar as duffymo, you should not extend any of the Java Collection classes until it is a must-do. Note that there are plenty of classes to hold almost any kind of common collections, and you have Queue and PriorityQueue that can help you in your real work.
The best solution would be as pointed by duffymo, composition instead of extending a Java Collection:
public class ProcessQueue<T> {
private List<T> data = new ArrayList<T>();
//rest of code...
}
Or creating a new implementation of an interface, like Queue or List.
public class ProcessQueue<T> implements Queue<T> {
//Queue interface methods implementation...
}

Java, declare variable with multiple interfaces?

In Java, is it possible to declare a field/variable whose type is multiple interfaces? For example, I need to declare a Map that is also Serializable. I want to make sure the variable references a serializable map. The Map interface does not extend Serializable, but most of Map's implementations are Serializable.
I'm pretty sure the answer is no.
Follow up: I'm fully aware of creating a new interface that extends both Map and Serializable. This will not work as existing implementations (such as HashMap) do not implement my new interface.
You can do it with generics, but it's not pretty:
class MyClass<T,K,V extends Serializable & Map<K,V>> {
T myVar;
}
There is no need to declare the field/variable like that. Especially since it can only be tested runtime and not compile time. Create a setter and report an error should the passed Map not implement Serializable.
The answers recommending that you create your own interface are of course not very practical as they will actively prohibit sending in things that are Maps and Serializable but not your special interface.
It's possible to do this using some generics tricks:
public <T extends Map<?,?> & Serializable> void setMap(T map)
The above code uses generics to force you to pass a map which implements both interfaces. However, note that a consequence of this is that when you actually pass it the maps, they will probably need to be either marked as serializable or of a map type which is already serializable. It also is quite a bit more difficult to read. I would document that the map must be serializable and perform the test for it.
public interface MyMap extends Map, Serializable {
}
will define a new interface that is the union of Map and Serializable.
You obviously have to then provide a suitable implementation of this (e.g. MyMapImpl) and you can then provide variable references of the type MyMap (or Map, or Serializable, depending on the requirements).
To address your clarification, you can't retrofit behaviour (e.g. a serializable map). You have to have the interface and some appropriate implementation.
I voted up Brian's answer, but wanted to add a little higher-level thought..
If you look through the SDK, you'll find that they rarely (if ever) pass around actual collection objects.
The reason for that is that it's not a very good idea. Collections are extremely unprotected.
Most of the time you want to make a copy before passing it off and pass the copy so that any modifications to the collection won't change the environment for something else that's relying on it. Also, threading becomes a nightmare--even with a synchronized collection!
I've seen two solutions, one is to always extract an array and pass it. This is how the SDK does it.
The other is to ALWAYS wrap collections in a parent class (And I mean encapsulate, not extend). I've gotten into this habit and it's very worth while. It doesn't really cost anything because you don't duplicate all the collection methods anyway (actually you rarely duplicate any of them). In fact what you end up doing is moving "Utility" functionality from other classes distributed all over your code into the wrapper class, which is where it should have been in the first place.
Any method with a signature that matches "method(collection,...)" should almost certainly be a member method of that collection, as should any loops that iterate over the collection.
I just have to throw this out every now and then because it's one of those things I didn't get for a while (because nobody championed the concept). It always seems like it's going to have some drawback but having done this for a while and seeing the problems it solved and code it eliminated, I can't even imagine any possible drawbacks myself, it's just all good.
You can achieve this by making your own Interface, which extends the interfaces you want
public interface SerializableMap<K, V> extends Map<K, V>, Serializable {
}
In my case it worked just to declare the concrete type:
HashMap<String, String> mySerializableMap = new HashMap<>();
It allowed me to use the Map methods (like put) and pass the map to methods that required a Serializable, without casting. Not perfect when we’ve learned to program towards interfaces, but good enough for me in the situation I was in.
If you really insist: As has been noted, declaring a combined interface alone does not solve the problem since the concrete classes we already have do not implement our combined interface even when they do implement each of the two interfaces we combine. I use it as a first step on the way, though. For example:
public interface SerializableMap<K, V> extends Map<K, V>, Serializable {
// No new methods or anything
}
The next step is also declaring a new class:
public class SerilizableHashMap<K, V> extends HashMap<K, V> implements SerializableMap<K, V> {
private static final long serialVersionUID = 4302237185522279700L;
}
This class is declared to implement the combined interface and thus can be used wherever one of those types is required. It extends a class that already implements each of the interfaces separately, therefore there’s nothing more we need to do. And now we have got what you asked for. Example of use:
public static void main(String[] args) {
SerializableMap<String, String> myMap = new SerilizableHashMap<>();
// myMap works as a Map
myMap.put("colour1", "red");
myMap.put("colour2", "green");
// myMap works as a Serializable too
consumeSerializable(myMap);
}
public static void consumeSerializable(Serializable s) {
// So something with the Serializable
}
For most purposes I suggest that this is overkill, but now I have at least presented it as an option.
Link: What does it mean to “program to an interface”?
You can't really do it if you want to keep using the existing Map implementations.
An alternative would be to make a helper class, and add a method like this one:
public static Serializable serializableFromMap(Map<?, ?> map) {
if (map instanceof Serializable) {
return (Serializable)map;
}
throw new IllegalArgumentException("map wasn't serializable");
}
Nope, you'll pretty much need to cast.

Categories

Resources