Since we are basically requiring every EventCollector to be constructed with
a single parameter (which should be a case class), this trait is required to
be extended by that parameter. The type parameter exists solely for the
purpose of type inference, so we can do getOrAdd(Rate(...)), and simply by
supplying the Rate (which returns a RateParams, which extends
MetricParams[Rate]), the method can infer that it should be returning a Rate
Since we are basically requiring every EventCollector to be constructed with a single parameter (which should be a case class), this trait is required to be extended by that parameter. The type parameter exists solely for the purpose of type inference, so we can do getOrAdd(Rate(...)), and simply by supplying the Rate (which returns a RateParams, which extends MetricParams[Rate]), the method can infer that it should be returning a Rate