Description
Hi folks! Really excited, but I admit I have a hard time reading the specification and couldn't find good examples to refer to.
Feel free to close if these are all handled, or shouldn't be handled (though I suspect they should). Most of these questions come from wanting to avoid so-called "primitive obsession" in our code, i.e. over-using primitives such as int
for dubious reasons (convenience, terseness, performance):
-
Can the "constructor" have logic similar to below?
I understand it will be possible to do so-called "unsafe" casts (possibly catchable with a lint), but for the "normal" use case, can I require validation before (explicit) conversion? For example, can I limit the
Level
type to integer values of 1 through 20?/// A level of a character in D&D 5e. 1-20 inclusive. final class Level { final int value; Level(this.value) { RangeError.checkValueInInternval(value, 1, 20); } } extension type Level(int i) { /* what do I write here? */ }
-
Is
==
andhashCode
forwarded for me? If so, how about these cases?In short, if
IdNumber(1) == 1
, I'm going to be sad.extension type Strength(i) {} extension type Dexterity(i) {} void main() { final strength = Strength(3); final dexterity = Dexterity(3); final constitution = 3; print(strength == strength); // true (I hope) print(strength == dexterity); // false (I hope), if it's true I ... understand, but hope a lint will catch this. print(strength == constitution); // false (I hope), if it's true I ... understand, but hope a lint will catch this. }
-
Is my/can my extension type be, say,
Comparable
?extension type Level(int i) implements Comparable<Level> { /* what do I write here? */ }
Is it comparable by default because
int
is?What if I'm wrapping a type that isn't comparable, such as
Uri
?
I'm worried that without support for these 3 scenarios, it's still going to be attractive to either continue using primitives, or extension types will be used, but they'll lack a lot of the flair of the pattern in say, Rust's newtype idiom.
Thanks for listening!