In general use this would be suicide in a managed language where the overhead of an object for every int could mean a huge jump in memory usage and GC wouldn't be worth the improvements. The actual implementation in Java would also be extremely ugly, for example:
class EventID {
private final int id;
public EventID(int anID) {
id = anID;
}
}
The class doesn't even contain basic methods like a way to get the ID, compare or hash it which with an int you get for free and it is still a fair wedge of code. Lombok's @Data annotation can really improve classes like this and make the language feel more declarative.
I have found the best language to implement this is c++, the following is my proof of concept implementation:
template
class TypedInt
{
public:
const int value;
TypedInt(int v) : value(v) {};
TypedInt operator + (TypedInt num)
{
TypedInt result(value + num.value);
return result;
}
TypedInt operator = (const int other)
{
TypedInt result(other);
return result;
}
};
class TypedInt
{
public:
const int value;
TypedInt(int v) : value(v) {};
TypedInt
{
TypedInt
return result;
}
TypedInt operator = (const int other)
{
TypedInt
return result;
}
};
This allows the following usage:
struct eventid {};
typedef TypedInt EventId;
typedef TypedInt
EventId i = 2, j = 3;
EventId result = i + j;
Overall this feels natural to use. If I was actually using class then the other operators such as == could be implemented without problems.
One of the benefits of c++ is that an object wrapping an int does not take more memory than an int would, during compilation this abstraction is apparently stripped away.