Both the examples are wrong.
A service doesn't normally implement the ContainerInjectionInterface interface. It can be implemented by other classes, for example the AggregatorController class, which is not a service, since it is not listed in the aggregator.services.yml file of the Aggregator module.
As described in Services and Dependency Injection Container, what a module maintainer needs to do to define a new service is:
- Choose a unique machine name for your service. Typically, this should start with your module name. Example: mymodule.myservice.
- Create a PHP interface to define what your service does.
- Create a default class implementing your interface that provides your service. If your class needs to use existing services (such as database access), be sure to make these services arguments to your class constructor, and save them in member variables. Also, if the needed services are provided by other modules and not Drupal Core, you'll want these modules to be dependencies of your module.
- Add an entry to a modulename.services.yml file for the service. See Discovering existing services above, or existing *.services.yml files in Core, for the syntax; it will start with your machine name, refer to your default class, and list the services that need to be passed into your constructor.
The second example is wrong because, instead of accessing \Drupal::service('current_user'), the constructor should just use the argument it gets.
Generally speaking, a service should never use the \Drupal class, but use the service container passed as argument to its create() (or createInstance()) method, or define a service as its arguments. In the latter case, the service will be passed as argument of its constructor.
The only case where a Drupal core service uses the \Drupal class in its constructor is when the arguments of a service has been changed. In that case, the service constructor uses code similar to the following one. (The code is the one used for JsCollectionOptimizer::__construct().)
public function __construct(AssetCollectionGrouperInterface $grouper, AssetOptimizerInterface $optimizer, AssetDumperInterface $dumper, StateInterface $state, FileSystemInterface $file_system = NULL) { $this->grouper = $grouper; $this->optimizer = $optimizer; $this->dumper = $dumper; $this->state = $state; if (!$file_system) { @trigger_error('The file_system service must be passed to JsCollectionOptimizer::__construct(), it is required before Drupal 9.0.0. See https://www.drupal.org/node/3006851.', E_USER_DEPRECATED); $file_system = \Drupal::service('file_system'); } $this->fileSystem = $file_system; }
As for the preferable/correct way to implement a service, which should not be confused with overriding the default class used for a service, there is just a way, which is the one I quoted.