Skip to content

Instantly share code, notes, and snippets.

@jamie-allen
Created September 11, 2014 03:45
Show Gist options
  • Save jamie-allen/392a1301fdb3b98cfd90 to your computer and use it in GitHub Desktop.
Save jamie-allen/392a1301fdb3b98cfd90 to your computer and use it in GitHub Desktop.
Initialization order is always tricky (not just in Scala). The order is top-down, so all these results are explainable through that. Using def will solve the initialization problem, as long as you can use defs (sometimes you don’t want to recompute the value on each access).
I find the following rule of thumb to work well:
- use abstract defs in traits by default, but...
- use a lazy val if the field will be used to access inner types (you need a stable path, so p.UserService works only when p is
a val). So this is not only an implementation concern, it opens up new possibilities for callers of this code.
- downgrade to a val if you are absolutely sure you don’t need laziness, or if concurrency implications of using a lazy value
are important (it synchronizes on the enclosing this to protect multiple threads from attempting to do it for the first time
simultaneously).
Regarding what the compiler enforcement, this is a policy, and there is no one-size fits all. It boils down to the uniform access principle. However, a tool like abide (or maybe a linter rule in the 2.12 compiler that you feed it) could enforce some of these rules (won’t catch all of them, it’s a hard problem).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment