Hi,
Post by Ralf UllrichJa, du übersiehst etwas und das Beispiel checkForSpecialKeys war im
Prinzip bereits Praxis-nah, aber vielleicht brauchst du auch einfach ein
IRHMap ist eine Variante des Map-Interfaces mit den von dir gewünschten
Definitionen für containsKey, containsValue und get.
isCompleteEnumMapping ist eine Methode, die überprüft, ob in einer Map
für jeden möglichen Wert eines Enum-Typs ein passendes Mapping vorhanden
ist. Wie du siehst, lässt sich diese Methode mit der "herkömmlichen" Map
einwandfrei implementieren. Aber mit der IRHMap gibt es dann Probleme.
Viel Spaß beim durchdenken und experimentieren. (Wenn du es schaffst
eine funktionierende Implementation der Methode für IRHMap vorzuweisen,
wäre ich sehr daran interessiert. Wichtig: die unten aufgeführten
Dummy-Aufrufe für IRHMap sollten sich alle kompilieren lassen.)
Danke für das (ausführliche und Praxis-nahe!) Beispiel!
(Leider war ich zwischendurch Mittagessen, daher meine verspätete
Antwort :-)
Allerdings bestätigt das ganze mein Argument aus meinem letzten Posting
in diesem Subthread (oder zumindest *fühle* ich mich bestätigt -
vielleicht kannst Du das ja widerlegen):
Du bringst hier IMHO ein Design (genauer *eine* Methoden-Deklaration),
die ich als so nicht sinnvoll ansehen würde, und sich in der Tat auch
nicht exakt parametrisieren läßt. Allerdings läßt sich das abstrakte
Problem (bei gleicher Funktionalität) sehr einfach lösen, wenn man die
Methoden-Deklaration geringfügig ändert (um nicht zu sagen sogar
vereinfacht):
Aus ...
public static boolean isCompleteEnumMapping(Class<? extends Enum> clz,
IRHMap<? extends Enum, ?> map)
... mach ...
public static <K> boolean isCompleteEnumMapping(K[] ks, IRHMap<K, ?> map)
Das ist IMHO viel einfacher, plausibler und sogar flexibler, weil auch
eine weitere Art von Aufruf funktioniert, von denen ich für jede der
Maps eine in den Test-Teil angehängt habe. Den kompletten Source hänge
ich mal unten an.
Wie gesagt, Du könntest jetzt argumentieren, dass (um alten Code zu
parametrisieren) vorher ein Mini-Refactoring nötig ist. Aber das ist
(A) mit einer IDE wie Eclipse quasi vollautomatisch machbar
(B) sowieso meistens nötig, wenn man alten Code "tunen" will
(C) sollte das kein Argument sein für eine Verkomplizierung des neuen Codes
Bin gespannt auf Deine anderen Einwände.
Ciao,
Ingo
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class GenericDemo
{
public interface IRHMap<K, V>
{
int size();
boolean isEmpty();
boolean containsKey(K key);
boolean containsValue(V value);
V put(K key, V value);
V remove(K key);
void putAll(Map<? extends K, ? extends V> t);
void clear();
Set<K> keySet();
Collection<V> values();
Set<Map.Entry<K, V>> entrySet();
boolean equals(Object o);
int hashCode();
}
enum NUMBERS {
ONE, TWO, THREE, FOUR
}
enum LETTERS {
ALPHA, BETA, GAMMA, DELTA
}
public static boolean isCompleteEnumMapping(Class<? extends Enum> clz,
Map<? extends Enum, ?> map)
{
for (Enum e : clz.getEnumConstants())
{
if (!map.containsKey(e))
return false;
}
return true;
}
public static <K> boolean isCompleteEnumMapping(K[] ks, IRHMap<K, ?> map)
{
for (K e : ks)
{
if (!map.containsKey(e)) // no compile time error!!
return false;
}
return true;
}
public static void main(String[] args)
{
Map<NUMBERS, String> mapOne = new HashMap<NUMBERS, String>();
mapOne.put(NUMBERS.ONE, "1");
mapOne.put(NUMBERS.TWO, "2");
mapOne.put(NUMBERS.THREE, "3");
mapOne.put(NUMBERS.FOUR, "4");
Map<LETTERS, String> mapTwo = new HashMap<LETTERS, String>();
mapTwo.put(LETTERS.ALPHA, "1");
mapTwo.put(LETTERS.BETA, "2");
mapTwo.put(LETTERS.GAMMA, "3");
mapTwo.put(LETTERS.DELTA, "4");
Map<Enum, String> mapThree = new HashMap<Enum, String>();
mapThree.putAll(mapOne);
mapThree.putAll(mapTwo);
isCompleteEnumMapping(NUMBERS.class, mapOne); // true!
isCompleteEnumMapping(LETTERS.class, mapTwo); // true!
isCompleteEnumMapping(NUMBERS.class, mapThree); // true!
isCompleteEnumMapping(LETTERS.class, mapThree); // true!
// dummies for IRHMap
IRHMap<NUMBERS, String> irhOne = null;
IRHMap<LETTERS, String> irhTwo = null;
IRHMap<Enum, String> irhThree = null;
isCompleteEnumMapping(NUMBERS.class.getEnumConstants(), irhOne);
GenericDemo.<NUMBERS> isCompleteEnumMapping(new NUMBERS[] {
NUMBERS.ONE,
NUMBERS.TWO}, irhOne);
isCompleteEnumMapping(LETTERS.class.getEnumConstants(), irhTwo);
GenericDemo.<LETTERS> isCompleteEnumMapping(new LETTERS[] {
LETTERS.ALPHA,
LETTERS.BETA}, irhTwo);
isCompleteEnumMapping(NUMBERS.class.getEnumConstants(), irhThree);
isCompleteEnumMapping(LETTERS.class.getEnumConstants(), irhThree);
GenericDemo.<Enum> isCompleteEnumMapping(new Enum[] { LETTERS.ALPHA,
NUMBERS.ONE}, irhThree);
}
}