3 ms·
You could potentially do the same thing with a class but it'd be really verbose: Class Age { private int value = null; public boolean SetValue(int value)
by bdw5204 3y ago
You could potentially do the same thing with a class but it'd be really verbose:
Class Age {
private int value = null;
public boolean SetValue(int value) {
if (value >= 0 && value <= 150) {
this.value = value;
return true;
}
return false;
}
public int getValue() {
return this.value;
}
}
That's approximately what the equivalent would look like in any language that supports classes (any errors are because it was typed on my phone). Being able to do that in 1 line would be much more convenient. That's why most programmers working in those languages just define age as an int and move on.
- tored 3y agoNot only in one line but also you don't need to wrap your function argument with a class instantiation, you can just pass the integer into the function you are calling and the compiler takes care of the rest. And that is a problem with many class based languages, that a class can't work as a primitive, compare Java's int vs Integer. program TestType; type age = 0..150; procedure test(age:age); begin writeln(age); end; begin test(100); test(200); end.
- Jtsummers 3y agoThat's a runtime check which does part of what Ada will do. Ada will also perform compile time checks related to uses of these restricted range variables. SPARK can go even further and detect potential overflow/underflow errors (and other things) forcing you to add preconditions (one resolution) to functions that declare that the values being added (or otherwise operated on) are small enough that overflow won't happen. Ada will also use a reasonable storage size. If Age is ranged [0,150] then it can place it in a single byte (you can also influence the storage size so you can increase this if you want for some reason), there is less memory overhead than an object. Since it's a range it brings in (automatically) all the arithmetic operations you'd expect. EDIT: Regarding storage. That's technically implementation defined. GNAT, at least, will use a reasonable storage size by default, you have to override it and ask for something bigger. I had occasion to use Green Hills years ago and it did the same as I recall. I'd expect any other commercial implementation to use an appropriate size and not something absurdly large like 64 bits for a range that easily fits in 8 bits, it would not fit their general market (safety-critical, performance-critical, real-time, and embedded systems). Poor use of memory could cripple the utility of a compiler in these kinds of systems (especially performance-critical, real-time, and embedded).
- kaba0 3y agoYou can’t generally make it a strictly compile-time feature, as far as I know. You do need what constitutes to overflow checks, basically.
- Jtsummers 3y agoYes, but Ada does offer some compile time checks. That example only does the runtime check part of range checking, it does do compile time checking for type mismatches (or would in most statically typed OO languages). And SPARK offers more compile time checks than plain Ada (but it restricts what you can do since it's a subset of Ada, useful within specific packages or for libraries but not necessarily globally depending on circumstances). Ada also offers the option to turn off the checks if you think you know what you're doing (you've proved out your system with SPARK, a lot of testing, or a lot of other analysis). For instance the class based version won't catch this until runtime (I'll assume some operator overloading for ease of demonstration, syntax is C-ish just because it's more engrained in my fingers): // suppose range is 0..127 my_type val = 200; // runtime error with the class version, compile time in Ada my_type a, b, c; // somehow a and b get assigned values c = a + b; // SPARK can warn about potential overflow here, class based version won't, straight Ada won't
- vips7L 3y agoThis is horrible design. It’s mutable and your returning Boolean values for whether or not your operation was a success. Use exceptions. If you want to take the pure public data approach the better approach would probably be: record Age(int value) { Age { if (value < 0 || value > 150) throw new IllegalArgumentException(value); } } Ultimately what we need is Valhalla to deliver primitive classes.