Каковы преимущества использования черт над абстрактными классами?

Кто-нибудь может объяснить черты в Scala? Каковы преимущества черт над расширением абстрактного класса?

Ответ 1

Короткий ответ заключается в том, что вы можете использовать несколько признаков - они "стекируются". Кроме того, черты не могут иметь параметры конструктора.

Вот как укладываются черты. Обратите внимание, что упорядочение характеристик важно. Они будут называть друг друга справа налево.

class Ball {
  def properties(): List[String] = List()
  override def toString() = "It a" +
    properties.mkString(" ", ", ", " ") +
    "ball"
}

trait Red extends Ball {
  override def properties() = super.properties ::: List("red")
}

trait Shiny extends Ball {
  override def properties() = super.properties ::: List("shiny")
}

object Balls {
  def main(args: Array[String]) {
    val myBall = new Ball with Shiny with Red
    println(myBall) // It a shiny, red ball
  }
}

Ответ 2

Этот сайт дает хороший пример использования признаков. Одно из преимуществ заключается в том, что вы можете расширить несколько признаков, но только один абстрактный класс. Черты решают многие проблемы с множественным наследованием, но позволяют повторное использование кода.

Если вы знаете рубин, черты похожи на миксы

Ответ 4

package ground.learning.scala.traits

/**
 * Created by Mohan on 31/08/2014.
 *
 * Stacks are layered one top of another, when moving from Left -> Right,
 * Right most will be at the top layer, and receives method call.
 */
object TraitMain {

  def main(args: Array[String]) {
    val strangers: List[NoEmotion] = List(
      new Stranger("Ray") with NoEmotion,
      new Stranger("Ray") with Bad,
      new Stranger("Ray") with Good,
      new Stranger("Ray") with Good with Bad,
      new Stranger("Ray") with Bad with Good)
    println(strangers.map(_.hi + "\n"))
  }
}

trait NoEmotion {
  def value: String

  def hi = "I am " + value
}

trait Good extends NoEmotion {
  override def hi = "I am " + value + ", It is a beautiful day!"
}

trait Bad extends NoEmotion {
  override def hi = "I am " + value + ", It is a bad day!"
}

case class Stranger(value: String) {
}
Output :

List(I am Ray
, I am Ray, It is a bad day!
, I am Ray, It is a beautiful day!
, I am Ray, It is a bad day!
, I am Ray, It is a beautiful day!
)

Ответ 5

Черты полезны для смешивания функциональности в классе. Посмотрите http://scalatest.org/. Обратите внимание, как вы можете смешивать в разных доменах (DSL) в тестовый класс. посмотрите руководство по быстрому запуску, чтобы посмотреть на некоторые из DSL, поддерживаемые Scalatest (http://scalatest.org/quick_start)

Ответ 6

Подобно интерфейсам в Java, черты используются для определения типов объектов путем указания подписи поддерживаемых методов.

В отличие от Java, Scala позволяет частично реализовать свойства; то есть можно определить реализации по умолчанию для некоторых методов.

В отличие от классов, характеристики могут не иметь параметров конструктора. Черты похожи на классы, но которые определяют интерфейс функций и полей, которые классы могут предоставлять конкретные значения и реализации.

Черты могут наследоваться от других признаков или из классов.

Ответ 7

Я цитирую с сайта книги Программирование в Scala, первом выпуске и, более конкретно, раздел " To черта, или нет, чтобы отличить?" из главы 12.

Всякий раз, когда вы реализуете коллекцию поведения, используемую повторно, вам нужно будет решить, хотите ли вы использовать черту или абстрактный класс. Нет твердого правила, но этот раздел содержит несколько рекомендаций, которые следует учитывать.

Если поведение не будет повторно использовано, сделайте его конкретным классом. В конце концов, это не повторное поведение.

Если он может быть повторно использован в нескольких, не связанных между собой классах, сделать его чертой. Только черты могут быть смешаны в разных частях иерархии классов.

В приведенной выше ссылке содержится немного больше информации о чертах, и я предлагаю вам прочитать полный раздел. Надеюсь, это поможет.