Частично наследовать интерфейс в Java? - PullRequest
0 голосов
/ 08 мая 2018

Я хочу реализовать простой интерфейс Cache:

public interface Cache {
    Object get(Object key);
    Object put(Object key, Object value);
    void clear();
}

Я понял, что это часть интерфейса java.util.Map. Таким образом, такие объекты, как HashMap, должны передаваться функциям, которым необходим объект Cache.

Но с другой стороны, я не хочу, чтобы мой собственный класс Cache реализовывал весь интерфейс Map, потому что мне действительно не нужны другие методы, кроме этих трех.

Ява не является языком типа "утка", так что как лучше в этой ситуации?

Ответы [ 3 ]

0 голосов
/ 08 мая 2018

В java таких функций нет.

Я думаю, что лучшее, что вы можете сделать, - это создать оболочку HashMap по вашему усмотрению.

Интерфейс - это контракт. Реализованный класс должен выполнить контракт, внедрив виртуальные / абстрактные методы.

Ваш CacheImpl только выполняет контракт с интерфейсом Cache. Между тем HashMap только выполняет контракт с интерфейсом Map.

Метод совместного использования интерфейса Cache и Map с одинаковыми сигнатурами, но для него требуется другой контракт / реализация.

Вы действительно не можете определить, совместим ли интерфейс с методом Object put(Object key, Object value);, совместим с вашим интерфейсом Cache или нет, потому что вы не понимаете, какой контракт обеспечивает этот интерфейс.

Таким образом, в Java, если они не обеспечивают семантику для создания вида «родительского» * ​​1023 * интерфейса существующего интерфейса, вы не можете сделать это.

0 голосов
/ 08 мая 2018

Если я понимаю ваш вопрос, вы спрашиваете, как поддержать интерфейс с существующим классом Java, таким как HashMap.

Вам нужно будет создать собственную реализацию, которая реализует ваш интерфейс и расширяет HashMap.

Методы интерфейса делегируют действие HashMap. Таким образом, ваш пользовательский класс будет отвечать потребностям интерфейса для любого метода с подписью вашего интерфейса.

Рабочий пример, который я собрал вместе, чтобы продемонстрировать, как сделать то, что вы просите, с помощью Generics:

Интерфейс кэша:

package interfaces;

public interface Cache<K,V> {
    V get(K key);
    V put(K key, V value);
    void clear();
}

Реализация:

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();
    }
}

Затем вы можете использовать его так:

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;
    }
}
0 голосов
/ 08 мая 2018

Я думаю, вы можете обернуть карту внутри реализации Cache класса

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();
    }
}

Я добавил пример с Generic, но вы всегда можете использовать Object в качестве ключа и значения.

Итак, в моем примере, чтобы сделать его потокобезопасным, мы можем ConcurrentHashMap, который уже thread safe и хорошо реализован. Я предлагаю использовать класс Factory для создания объекта кэша, как показано ниже.

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<>());
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...