Firstly apologies if I'm using the wrong term by picking the word 'semantics.'
I'm a big fan of generics in Java for all the obvious reasons. It helps me enormously as I work with a huge variety of odd bits of code and I often have to go back to old stuff. Today I found myself with a classic parameter misplacement bug which I probably wouldn't have written in the pre-generic days - they have made me a bit lazy.
I'd like to know if there is a language feature, either in Java or perhaps as a similar concept in other languages, which takes the type safety of generics and extends it to a kind of semantic safety. Specifically I want to help trap the kind of errors which result from putting the right thing in the wrong place.
A simple example:
Map<String, String> myMap = new HashMap<String, String>();
String myKey = "key";
String myVal = "value";
myMap.put(myVal, myKey);
Which no compiler will catch. I could subclass make wrappers to give me a String
Key
type and a Value
type, I suppose. I could name my variables to indicate their use (as I've done in this example). What else?
So my questions are:
Thanks
I have always used maps that have two different types for the key and value, never the same types. I suppose there are times when you would want to use the same type for the key and value as in your example. I can't think of any languages off the top of my head that have this feature.
Actually I have used Clojure before and for maps it uses a keyword for the key which looks like :key
and then the value is just whatever the value is. It makes it clearer but now i'm dabbling into functional programming which is not really the question you were asking. Check out Lisp-like languages.
I think its just a case of not getting them mixed up, Java certainly cannot enforce this kind of checking.
Best advice would be to use different types for the key and value so the compiler can detect the type error, or name the key and value variables explicitly as you have done.
You can't subclass String. You can create your own classes, though, and use them. So if you are mapping Persons to Roles, for instance, you can define a Person like
class Person {
String id;
String firstName;
String lastName;
...
}
and a Role like
class Role {
int id;
String name;
}
(Note these will need to define an equals and hashcode method)
and have a mapping from person to role like:
Map<Person, Set<Role>> myMap = new HashMap<Person, Set<Role>>();
so that the type system enforces what you can put where (as opposed to having a map of strings to sets of ints). Not sure what this is called but "Domain Objects" and "Abstract Data Types" seem related.
In the absence of type-checking the fallback is to write unit tests.
You could use a more extensive type system, avoiding using the same type in parameter lists.
i.e.
Map<Key, Value> myMap = new HashMap<Key, Value>();
Key myKey = // some key
Value myVal = // some value
myMap.put(myVal, myKey); //compiler error
On some level you need to explain the concepts and how they interact with operations to have the language check anything, interested in whether there are any alternative approaches out there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With