If I’m understanding correctly, you are wondering why inline classes do not allow for implicitly construction*.
Just to make sure we’re on the same page:
- This request could include any class with a single param (e.x.
class Password(val value: String) but we can limit it to inline classes if the argument would be stronger.
- Because it’s an inline class there will not be an init block.
- Typealias do allow your example code:
typealias Email = String
val email: Email = "Don't try this in production" // This works
inline class Password(val value: String)
val securePassword: Password = "Don't try this in production" // This does not work
So you ask why would this not be allowed if it’s simpler?
I’d reword “simpler” to “fewer characters” or “more concise”, whichever is more convincing.
I think the reason to not allow this is that it makes things less clear. Although it is more concise, it blurs the meaning of an inline class IMO. The whole point of using a wrapping class over a typealias is to prevent code similar to this example.
Here’s my take. I talk about inline types but I would apply the same reasoning to a normal wrapping class.
One of the primary goals of inline types is to make them distinctly different things than their wrapped type. We don’t want the consumer assigning to/from, using in place of, or comparing inline types to their backing type without code explicitly allow it.
This is why inline classes differ from typealias. Both inline classes and typealias create a class that can be used to name a primitive type. And both can be used as targets for methods/params/generics (anywhere a type is used).
But unlike typealias, with inline classes we get to say that our inline class is not its backing type. No applying code that wasn’t explicitly written to handle our inline class, no assignments to the encoded type, no in-place-of’s, no implicitly conversions, no treating
Password like it’s a
String– all because we don’t want that as the author (otherwise we would use typealias).
When you remove the explicit constructor call for inline classes like in your suggestion, you make the distinction a little more blurry to the reader. One might read it and think that a
Password is a string (or at least could be considered as such). While we as the authors of the class know that
Password is backed by a
String, we’ve made the conscious decision to block the consumer from writing code that treats it as a
If we instead wanted consumers to know about the connection between Password and it’s internal encoding as a
String, we can use typealias. Otherwise, we use a wrapping class–If that class is encoded as a primitive or
String, it’s probably a good idea to make that wrapper an inline class for performance reasons.
We don’t want the consumer to consider
Password's internal encoding over its actual type. Inline types force this distinction in code and the way we construct an inline classes should not suggest to the reader that
String is any different than a normal constructor param.