Reputation: 163
I want to implement a simple Cache interface:
public interface Cache {
Object get(Object key);
Object put(Object key, Object value);
void clear();
}
I realized it's part of interface java.util.Map. So objects like HashMap should be able to be be passed to functions needing a Cache object.
But on the other hand I don't want to make my own Cache class implement the whole Map interface because I don't really need other methods other than these three.
Java is not a duck-typed language, so what's the best practice in this situation?
Upvotes: 6
Views: 340
Reputation: 7315
I think you can wrapper Map inside the Implementation of Cache
class
class CacheImpl<K, V> implements Cache<K, V> {
Map<K, V> cacheMap;
CacheImpl() {
this(new LinkedHashMap<>());
}
CacheImpl(Map<K,V> cacheMap) {
this.cacheMap = cacheMap;
}
@Override
public V get(K key) {
return cacheMap.get(key);
}
@Override
public V put(K key, V value) {
return cacheMap.put(key, value);
}
@Override
public void clear() {
cacheMap.clear();
}
}
I have added the example with the Generic but you are always free to Use Object as the key and value.
So, in my example to make it thread safe We can we ConcurrentHashMap
which is already thread safe
and well implemented. I will suggest having a Factory class to create the cache object like below.
class CacheImplFactory {
public static <K, V> Cache<K, V> newSimpleCache() {
return new CacheImpl<K, V>();
}
public static <K, V> Cache<K, V> newSynchronizedCache() {
return new CacheImpl<K, V>(new ConcurrentHashMap<>());
}
public static <K, V> Cache<K, V> newWeakCache() {
return new CacheImpl<K, V>(new WeakHashMap<>());
}
}
Upvotes: 2
Reputation: 686
If I understand your question, you're asking how to back the interface with an existing java class like HashMap.
You will have to create your own implementation that implements your interface, and extends HashMap.
The Interface methods will delegate the action to the HashMap. In this manner, your custom class will meet the interface needs for any Method with a signature of your interface.
A working example I threw together to showcase how to do what you're asking with Generics:
The Cache Interface:
package interfaces;
public interface Cache<K,V> {
V get(K key);
V put(K key, V value);
void clear();
}
The Implementation:
package classes;
import java.util.HashMap;
import interfaces.Cache;
public class MyCache<K,V> extends HashMap<K,V> implements Cache<K,V> {
private static final long serialVersionUID = 1L;
@Override
public V get(Object key) {
return super.get(key);
}
@Override
public V put(K key, V value) {
return super.put(key, value);
}
@Override
public void clear() {
super.clear();
}
}
You can then use it like so:
import classes.MyCache;
import interfaces.Cache;
public class DoStuff {
private Cache<String,Integer> cache;
public void initCache() {
//This works
//Since MyCache implements Cache
MyCache<String,Integer> mCache=new MyCache<String,Integer>();
setCache(mCache);
//This will not
//Since HashMap does not implement Cache
HashMap<String,Integer> mMap=new HashMap<String,Integer>();
setCache(mMap);
}
public void setCache(Cache<String,Integer> c) {
cache=c;
}
public Cache<String,Integer> getCache() {
return cache;
}
}
Upvotes: 1
Reputation: 18235
There are no such features in java.
I think the best you can do is to create a wrapper of HashMap as you concern.
An interface is a contract. The implemented class should fullfill the contract by implement the virtual / abstract methods.
Your CacheImpl
only fullfills the contract with Cache
interface. Meanwhile HashMap
only fullfills the contract with Map
interface.
The Cache
and Map
interface share method with same signatures but they requires different contract / implementation.
You really can not determine if an interface contains the method Object put(Object key, Object value);
is compatible with your Cache
interface or not, because you don't understand which contract that interface provide.
So in Java, unless they provide semantic to create kind of "parent" interface of existing interface, you cannot do that.
Upvotes: 2