Обобщенные классы (Generic classes) - это классы, обладающие параметрическим полиморфизмом (т. е. классы, которые изменяют свое поведение в зависимости от приписываемого им типа. Этот тип указывается в квадратных скобках [] сразу после имени класса). Они особенно полезны для создания коллекций.
Объявление обобщенного класса
Для объявления обобщенного класса необходимо после имени добавить тип в квадратных скобках [] как еще один параметр класса. По соглашению обычно используют заглавные буквы A, хотя можно использовать любые имена.
class Stack[A] {
  private var elements: List[A] = Nil
  def push(x: A): Unit =
    elements = x :: elements
  def peek: A = elements.head
  def pop(): A = {
    val currentTop = peek
    elements = elements.tail
    currentTop
  }
}
class Stack[A]:
  private var elements: List[A] = Nil
  def push(x: A): Unit =
    elements = x :: elements
  def peek: A = elements.head
  def pop(): A =
    val currentTop = peek
    elements = elements.tail
    currentTop
Данная реализация класса Stack принимает в качестве параметра любой тип A. Это означает что список, var elements: List[A] = Nil, может хранить только элементы типа A. Процедура def push принимает только объекты типа A (примечание: elements = x :: elements переназначает elements в новый список, созданный путем добавления x к текущим elements).
Здесь Nil — это пустой List, и его не следует путать с null.
Использование
Чтобы использовать обобщенный класс, поместите конкретный тип в квадратные скобки вместо A.
val stack = new Stack[Int]
stack.push(1)
stack.push(2)
println(stack.pop())  // выведет 2
println(stack.pop())  // выведет 1
val stack = Stack[Int]
stack.push(1)
stack.push(2)
println(stack.pop())  // выведет 2
println(stack.pop())  // выведет 1
Экземпляр stack может принимать элементы типа Int. Однако, если тип имеет подтипы, то они также могут быть приняты:
class Fruit
class Apple extends Fruit
class Banana extends Fruit
val stack = new Stack[Fruit]
val apple = new Apple
val banana = new Banana
stack.push(apple)
stack.push(banana)
class Fruit
class Apple extends Fruit
class Banana extends Fruit
val stack = Stack[Fruit]
val apple = Apple()
val banana = Banana()
stack.push(apple)
stack.push(banana)
Классы Apple и Banana наследуются от Fruit так, что мы можем засунуть экземпляры Apple и Banana в пачку Fruit.
Примечание: подтипы обобщенных типов - *инвариантны*. Это означает, что если у нас есть стэк символов типа Stack[Char], то он не может быть использован как стек интов типа Stack[Int]. Это нежелательное поведение, потому как позволило бы нам добавлять в стек символов целые числа. В заключение, Stack[A] является подтипом Stack[B] тогда и только тогда, когда B = A. Поскольку это может быть довольно строгим ограничением, Scala предлагает механизм вариативного описания параметров типа для контроля за поведением подтипов.
Contributors to this page:
Contents
- Введение
 - Основы
 - Единобразие типов
 - Классы
 - Значения Параметров По умолчанию
 - Именованные Аргументы
 - Трейты
 - Кортежи
 - Композиция классов с трейтами
 - Функции Высшего Порядка
 - Вложенные Методы
 - Множественные списки параметров (Каррирование)
 - Классы Образцы
 - Сопоставление с примером
 - Объекты Одиночки
 - Регулярные Выражения
 - Объект Экстрактор
 - Сложные for-выражения
 - Обобщенные Классы
 - Вариантность
 - Верхнее Ограничение Типа
 - Нижнее Ограничение Типа
 - Внутренние классы
 - Члены Абстрактного Типа
 - Составные Типы
 - Самоописываемые типы
 - Контекстные параметры, также известные, как неявные параметры
 - Неявные Преобразования
 - Полиморфные методы
 - Выведение Типа
 - Операторы
 - Вызов по имени
 - Аннотации
 - Пакеты и Импорт
 - Объекты Пакета