Учебник по Скала

Обзор

Класс, объявленный с помощью ключевого слова abstract, называется классом abstract.

abstract class Pet(name: String) {
  var age: Int = 0              // concrete field

  def printName: Unit           // abstract method

  def printAge: Unit = {        // concrete method
    println(age)
  }
}

Абстрактный класс может иметь какабстрактные, так и неабстрактные (реализованные) методы. Как уже упоминалось, абстрактный класс также может иметь свои собственные реализованные поля и методы, которые не требуют реализации в подклассах. Обратите внимание, что мы не можем создать экземпляр абстрактного класса напрямую с помощью оператора new — если мы это сделаем, компилятор выдаст ошибку! Абстрактный класс может использоваться как базовый класс другого класса, который реализует отложенные/нереализованные члены. Абстрактные классы могут иметь параметры конструктора, а также параметры типа.

Назначение абстрактного класса

Цель класса abstract — функционировать как базовый класс с абстракциями, которые могут быть расширены подклассами для создания полных реализаций. В Scala мы можем добиться абстракции, используя либо абстрактный класс, либо trait.

Реализация/использование абстрактного класса

Используйте ключевое слово «extends», чтобы расширить абстрактный класс. Ожидается, что класс, который расширяет абстрактный класс, реализует все методы, определенные в этом абстрактном классе. Если расширяющий класс не реализует все методы и поля, определенные в абстрактном классе, расширяющий класс должен быть объявлен abstract . Обратите внимание, что класс может расширять только один абстрактный класс.

class Dog(name: String) extends Pet(name) {
  // Implementation of abstract method
  def printName: Unit = println("Hi there, I am " + name)
}

Переопределение реализованного метода

class Dog(name: String) extends Pet(name) {
  // Implementation of abstract method
  def printName: Unit = println("Hi there, I am " + name)

  // Overrides the implemented method to add more details
  override def printAge: Unit = {
    println(name + "'s age is " + age)
  }
}

Полный пример

abstract class Pet(name: String) {
  var age: Int = 0              // concrete field

  def printName: Unit           // abstract method

  def printAge: Unit = {        // concrete method
    println(age)
  }
}

class Dog(name: String) extends Pet(name) {
  // Implementation of abstract method
  def printName: Unit = println("Hi there, I am " + name)
}

object AbstractClassDemo extends App {
  val dogObj = new Dog("Jimmy")
  dogObj.printName
  dogObj.age = 2
  dogObj.printAge
}

Абстрактные поля «val» и «var»

Мы можем объявить абстрактные поля в абстрактном классе либо как val, либо как var, в зависимости от наших потребностей.

abstract class Pet (name: String) {
    val greeting: String  // abstract "val" field
    var age: Int          // abstract "var" field
}

Абстрактные поля работают в абстрактных классах (также и в трейтах) следующим образом:

  • Абстрактное поле var приводит к созданию методов getter и setter для поля.
  • Абстрактное поле val приводит к тому, что для поля генерируется метод получения, но не метод установки.

Абстрактные поля создаваться не будут!

Когда мы определяем абстрактное поле в абстрактном классе или trait, компилятор Scala не создает поле в результирующем коде; он генерирует только те методы, которые соответствуют полю val или var. Поскольку абстрактные поля не генерируются, когда мы предоставляем конкретные значения для абстрактных полей в наших конкретных классах, мы должны снова определить поля как val или var. Поскольку абстрактные поля фактически не существуют в абстрактном базовом классе или свойстве, ключевое слово override не требуется.

Взаимодействие с Java

  • Абстрактные классы полностью совместимы с Java.
  • Мы можем вызывать их из кода Java без каких-либо оболочек.

Когда использовать абстрактный класс вместо трейта?

trait более гибкий, чем абстрактный класс. Однако можно выбрать абстрактный класс вместо типажа по следующим причинам:

  • Хотите создать базовый класс, для которого требуются аргументы конструктора.
  • Хотите, чтобы код вызывался из кода Java.

Что нельзя сделать с абстрактным классом

Абстрактные классы не могут быть созданы, но они могут быть только подклассами (создание подклассов из абстрактного класса).

Различия и сходства с Java

Отличия

  • Никаких различий!

Сходства

  • Абстрактные классы не могут быть созданы, но они могут быть только подклассами.
  • Абстрактные классы могут иметь конструкторы.
  • Класс может расширять только один абстрактный класс.