Каковы плюсы использования черт над абстрактными классами? - PullRequest
80 голосов
/ 05 августа 2009

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

Ответы [ 7 ]

79 голосов
/ 05 августа 2009

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

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

class Ball {
  def properties(): List[String] = List()
  override def toString() = "It's 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's a shiny, red ball
  }
}
19 голосов
/ 05 августа 2009

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

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

5 голосов
/ 31 августа 2014
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!
)

4 голосов
/ 09 июля 2012

Это лучший пример, который я видел

Scala на практике: составление черт - стиль Lego: http://gleichmann.wordpress.com/2009/10/21/scala-in-practice-composing-traits-lego-style/

    class Shuttle extends Spacecraft with ControlCabin with PulseEngine{

        val maxPulse = 10

        def increaseSpeed = speedUp
    }
3 голосов
/ 18 декабря 2012

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

1 голос
/ 19 сентября 2014

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

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

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

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

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

1 голос
/ 28 ноября 2013

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

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

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

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

...