Які плюси використання рис перед абстрактними класами?


81

Хтось може пояснити риси в Скалі? Які переваги рис перед розширенням абстрактного класу?

Відповіді:


80

Коротка відповідь полягає в тому, що ви можете використовувати декілька рис - вони "складаються". Крім того, риси не можуть мати параметри конструктора.

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

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
  }
}

4
Відсутність параметрів конструктора майже компенсується використанням параметрів типу в рисах.
Jus12,

19

Цей сайт дає хороший приклад використання ознак. Однією з великих переваг ознак є те, що ви можете розширити декілька ознак, але лише один абстрактний клас. Трейти вирішують багато проблем із множинним успадкуванням, але дозволяють повторне використання коду.

Якщо ви знаєте рубін, риси подібні до міксів


5
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) {
}
Вихід:

Список (Я - Рей
, Я Рей, це поганий день!
, Я Рей, це прекрасний день!
, Я Рей, це поганий день!
, Я Рей, це прекрасний день!
)



3

Риси корисні для змішування функціональності в класі. Погляньте на http://scalatest.org/ . Зверніть увагу, як ви можете поєднувати різні тематичні мови (DSL) у тестовий клас. подивіться короткий посібник для початку, щоб переглянути деякі DSL, що підтримуються Scalatest ( http://scalatest.org/quick_start )


1

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

На відміну від Java, Scala дозволяє частково реалізувати риси; тобто можна визначити реалізації за замовчуванням для деяких методів.

На відміну від класів, риси можуть не мати параметрів конструктора. Риси схожі на класи, але які визначають інтерфейс функцій та полів, які класи можуть надати конкретні значення та реалізації.

Риси можуть успадковуватися від інших рис або від класів.


1

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

Кожного разу, коли ви реалізуєте багаторазову колекцію поведінки, вам доведеться вирішити, чи хочете ви використовувати ознаку або абстрактний клас. Чіткого правила не існує, але цей розділ містить кілька рекомендацій, які слід врахувати.

Якщо поведінка не буде використана повторно, зробіть це конкретним класом. Зрештою, це не багаторазова поведінка.

Якщо його можна використовувати повторно в декількох не пов’язаних між собою класах, зробіть це рисою. Тільки риси можна змішувати в різні частини ієрархії класів.

У наведеному вище посиланні є трохи більше інформації про риси, і я пропоную вам прочитати повний розділ. Сподіваюся, це допоможе.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.