Не зная деталей выбора дизайна в библиотеке коллекций, я думаю, что вижу здесь два варианта использования:
DRY.В некоторой степени внутренний, но наличие объекта-компаньона, который действует как фабричное здание из построителя конкретного типа, является общим шаблоном в библиотеке коллекций, поэтому рефакторинг его в класс, составляемый каждой реализацией коллекции, уменьшает дублирование.
Абстракция.Предоставление «компаньона» предоставляет клиентскому коду средство для создания новой коллекции того же типа, что и экземпляр, не обязательно зная, что это за тип.Это было бы полезно, если вы хотите создать более общие функции обработки коллекций, которые возвращают согласованные типы.
Вот несколько примеров того, как это может быть полезно:
scala> val a: Traversable[Int] = Set(1,2,3,4)
a: Traversable[Int] = Set(1, 2, 3, 4)
scala> a.companion(1,2,3)
res1: Traversable[Int] = Set(1, 2, 3)
scala> val b: Traversable[Int] = List(1,2,3,4)
b: Traversable[Int] = List(1, 2, 3, 4)
scala> b.companion(1,2,3)
res2: Traversable[Int] = List(1, 2, 3)
scala> def ends[T](c: Traversable[T]) : Traversable[T]= {
| c.companion(c.head, c.last)
| }
ends: [T](c: Traversable[T])Traversable[T]
scala> ends[Int](List(1,2,3,4,5))
res3: Traversable[Int] = List(1, 5)
scala> ends[Int](Set(1,2,3,4,5))
res4: Traversable[Int] = Set(5, 4)
Обратите внимание, что «конец» не знает, какой подтип Traversable он получает, но может вернуть новую коллекцию совместимого типа, созданную с использованием компаньона.