Tthe init block is called when the class is first loaded. The same applies to other global values (top level properties).
You can load the class several ways but another alternative is to force users of your code to call an explicit
initialize function on your object to control this functionality. Still, this is probably not the best design (all say why I think so lower in the reply).
I’m not sure I understand what you’re wanting to do here. The phrasing of it makes me suspect you want every newly constructed
FileValidator to automatically register itself with the
FileValidatorManager. This kind of automatic registration could be replaced by requiring the users to register the file validators themselves.
Still if you want all types of
FileValidators to be registered automatically without control, you could use an abstract class instead of an interface. Your
FileValidator class can do all of it’s initialization in it’s init block as it sees fit. Every subclass receives the guarantee (like all subclasses) that the parent is properly initialized before the subclass does it’s own specialized initialization.
This kind of initialization of state and ordering of initialization is a primary purpose behind classes. If you still want an interface that’s okay but in order to keep the behavior of registering all implementations, you’ll still need a general use class combined with some creational design pattern. (For example keep the
FileValidator but have all implementations extend
Since you’re using a global singleton for the manager that you want to use in all
FileValidators, your manager looks more like a companion object. After all, a companion object is defined as a member of every instance of a type. You might consider moving
FileValidatorManager into a companion object since that’s how you’re already using it.
Lastly, why are you using a singleton? A singleton is rarely the answer as it’s just another global. In some circles, saying the word
singleton is enough to trigger some people’s code-smell reflex
Your singleton for here means you give up a lot of control. You give up multi-tenency (e.i. Only one
FileValidatorManager group at time!). You also give up raw testing and mocking.
You could make
FileValidatorManager into a class and create a global
val that holds a default group. Even then I would avoid that and just initialize it for each application (or test suite, etc).
You’ll find that your entry points should be small and do all of this kind of initialization for your program. Having globals force unchangeable defaults causes a lot of pain. There’s always the exception for short throw-away scripts though.
Most of my main methods end up looking like 5-10 lines of creating all of my “singleton” objects and configuring them–same as you’d do for dependency injection or service registration.