← Back to context

Comment by masklinn

1 hour ago

I think you missed the issue at hand:

> even if you keep all your fields private, the constructor is still, inherently, public.

ShippingOptions and the literals / enums are part of the public API, so the user would just be writing

    ShippingOptions(Carrier.USPS, Conveyance.Air)

with no hint that they're doing anything wrong.

Dataclasses do have a `kw_only` option, but I'm not sure how well underscore prefixes would be understood as private parameters / a private ctor, whereas wrapping a clearly "private" type should be clear to everybody.

Glyph is not entirely correct on the "any class" bit as you can always break the default init path:

  class ShippingOptions:
      _ship: Literal["fast", "normal", "slow"]
      __init__ = None


  def shipFast() -> ShippingOptions:
      opts = object.__new__(ShippingOptions)
      opts._ship = "fast"
      return opts

however that's a pretty ugly pattern, and unlike the one they propose I doubt tooling would understand it.