Примеси (Mixin) - это трейты, которые используются для создания класса.
abstract class A {
val message: String
}
class B extends A {
val message = "I'm an instance of class B"
}
trait C extends A {
def loudMessage = message.toUpperCase()
}
class D extends B with C
val d = new D
println(d.message) // I'm an instance of class B
println(d.loudMessage) // I'M AN INSTANCE OF CLASS B
У класса D
есть суперкласс B
и трейт C
.
Классы могут иметь только один суперкласс, но много трейтов (используя ключевое слово extends
и with
соответственно).
Трейты и суперкласс могут иметь один и тот же супертип.
abstract class A:
val message: String
class B extends A:
val message = "I'm an instance of class B"
trait C extends A:
def loudMessage = message.toUpperCase()
class D extends B, C
val d = D()
println(d.message) // I'm an instance of class B
println(d.loudMessage) // I'M AN INSTANCE OF CLASS B
У класса D
есть суперкласс B
и трейт C
.
Классы могут иметь только один суперкласс, но много трейтов
(используя ключевое слово extends
и разделитель ,
соответственно).
Трейты и суперкласс могут иметь один и тот же супертип.
Теперь давайте рассмотрим более интересный пример, начиная с абстрактного класса:
abstract class AbsIterator {
type T
def hasNext: Boolean
def next(): T
}
abstract class AbsIterator:
type T
def hasNext: Boolean
def next(): T
Класс имеет абстрактный тип T
и методы стандартного итератора.
Далее создаем конкретную реализацию класса (все абстрактные члены T
, hasNext
, и next
должны быть реализованы):
class StringIterator(s: String) extends AbsIterator {
type T = Char
private var i = 0
def hasNext = i < s.length
def next() = {
val ch = s charAt i
i += 1
ch
}
}
class StringIterator(s: String) extends AbsIterator:
type T = Char
private var i = 0
def hasNext = i < s.length
def next() =
val ch = s charAt i
i += 1
ch
StringIterator
принимает String
и может быть использован для обхода по строке (например, чтоб проверить содержит ли строка определенный символ).
Теперь давайте создадим трейт который тоже наследуется от AbsIterator
.
trait RichIterator extends AbsIterator {
def foreach(f: T => Unit): Unit = while (hasNext) f(next())
}
У этого трейта реализован метод foreach
, который постоянно вызывает переданную ему функцию f: T => Unit
на каждом новом элементе (next()
) до тех пор пока в итераторе содержатся элементы (while (hasNext)
).
Поскольку RichIterator
- это трейт, ему не нужно реализовывать элементы абстрактного класса AbsIterator
.
trait RichIterator extends AbsIterator:
def foreach(f: T => Unit): Unit = while hasNext do f(next())
У этого трейта реализован метод foreach
, который постоянно вызывает переданную ему функцию f: T => Unit
на каждом новом элементе (next()
) до тех пор пока в итераторе содержатся элементы (while hasNext
).
Поскольку RichIterator
- это трейт, ему не нужно реализовывать элементы абстрактного класса AbsIterator
.
Мы бы хотели объединить функциональность StringIterator
и RichIterator
в один класс.
class RichStringIter extends StringIterator("Scala") with RichIterator
val richStringIter = new RichStringIter
richStringIter.foreach(println)
class RichStringIter extends StringIterator("Scala"), RichIterator
val richStringIter = RichStringIter()
richStringIter.foreach(println)
Новый класс RichStringIter
включает StringIterator
как суперкласс и RichIterator
как трейт.
Используя только одиночное наследование мы бы не смогли добиться того же уровня гибкости.
Contributors to this page:
Contents
- Введение
- Основы
- Единобразие типов
- Классы
- Значения Параметров По умолчанию
- Именованные Аргументы
- Трейты
- Кортежи
- Композиция классов с трейтами
- Функции Высшего Порядка
- Вложенные Методы
- Множественные списки параметров (Каррирование)
- Классы Образцы
- Сопоставление с примером
- Объекты Одиночки
- Регулярные Выражения
- Объект Экстрактор
- Сложные for-выражения
- Обобщенные Классы
- Вариантность
- Верхнее Ограничение Типа
- Нижнее Ограничение Типа
- Внутренние классы
- Члены Абстрактного Типа
- Составные Типы
- Самоописываемые типы
- Контекстные параметры, также известные, как неявные параметры
- Неявные Преобразования
- Полиморфные методы
- Выведение Типа
- Операторы
- Вызов по имени
- Аннотации
- Пакеты и Импорт
- Объекты Пакета