Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Partially inherit an interface in Java?

Tags:

java

oop

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?

like image 775
Ken Avatar asked May 08 '18 18:05

Ken


2 Answers

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.

like image 183
Mạnh Quyết Nguyễn Avatar answered Sep 26 '22 14:09

Mạnh Quyết Nguyễn


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<>());
    }
}
like image 25
Amit Bera Avatar answered Sep 25 '22 14:09

Amit Bera