java - Map from T to T -
say want use map
, have following requirement: want each key map value of same type.
map<???> map = ...; map.put(42, 15); map.put("hello world", 15); // compile time error, because cannot map string int. map.put("hello world", "foobar"); map.put(new foo(), new foo()); integer = map.get(42); string s = map.get("hello world"); foo f = map.get(new foo());
of course above code not compile trick map t
t
t
not defined @ instantiation. map returns same type parameter. of course made more fun, mapping t
list<t>
. without ugly casting?
scala's type system considered more advanced, there solution in scala?
if answer both of above questions no, there language supports such typing?
note: map in above code example of type takes 2 generic parameters. i'm not interested in map in particular, more in type system.
it's not precisely you're describing, well-known pattern in java typesafe heterogeneous container (effective java item 29), maps class<t>
instance of t
. guava provides classtoinstancemap
interface implements pattern.
in java, can jury-rig type describing, won't pretty.
public class ttmap extends forwardingmap<object, object> { private final hashmap<object, object> delegate = new hashmap<>(); @override protected map<object, object> delegate() { return delegate(); } @suppresswarnings("unchecked") public <t> t gettype(t key) { return (t)delegate().get(key); } @suppresswarnings("unchecked") public <t> t puttype(t key, t value) { return (t)delegate().put(key, value); } @override @deprecated public object put(object key, object value) { preconditions.checkstate(key == value || value.getclass().equals(key.getclass())); return delegate.put(key, value); } @override @deprecated public void putall(map<? extends object, ? extends object> map) { standardputall(map); } }
this uses forwardingmap
give map<object, object>
runtime constraint keys , values of same type. need use gettype()
, puttype()
avoid risk of runtime errors; put()
, putall()
can enforce constraint runtime exceptions. add putall(ttmap)
method, if wanted.
the key == value
check in put()
allows null
s long both key
, value
null. if 1 or other is, you'll nullpointerexception
@ class equality check.
also note @radiodef's comment - every type extends object
, there's no way - generics - prevent 2 types being cast object
, inserted. you'll need additional runtime checks address that.
if implementing map
isn't requirement, follow similar pattern (a private map<object, object>
, typed getters , setters) on new class easily.
Comments
Post a Comment