Расширение черты и типов - PullRequest
8 голосов
/ 29 ноября 2010

Я хотел бы иметь запечатанную черту, у которой есть объявленный метод, который возвращает фактический класс, который расширяет черту. Должен ли я использовать абстрактный тип, тип параметра или Есть ли другой хороший способ решить эту проблему?

sealed trait Foo {
  type T
  def doit(other: T): T
}

или

sealed trait Foo[T] {
  def doit(other: T): T
}

Обратите внимание, что T должен быть подтипом Foo в этом примере. Если я делаю это так, типа информация кажется слишком повторной:

case class Bar(name: String) extends Foo[Bar] {
  def doit(other: Bar): Bar = ...
}

Ответы [ 5 ]

4 голосов
/ 29 ноября 2010

Они в основном взаимозаменяемы. По словам Одерского, причина была в основном для полноты: это аналогично тому, что методы и поля (значения) могут быть либо абстрактными, либо передаваться как параметры, так и типы.

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

Вот статья, объясняющая все это: http://www.artima.com/weblogs/viewpost.jsp?thread=270195

2 голосов
/ 30 ноября 2010

Вы можете несколько сократить повторение, если ваш метод doit возвращает фабричную функцию:

trait Foo[T] { 
   self: T =>
   def doit: T => T 
}

case class Bar(name: String) extends Foo[Bar] {
   // note: types omitted 
   def doit = { other => Bar(name + other.name) }
}

Невозможно сделать то же самое с абстрактным типом:

trait Foo { 
   self: T => // won't compile because T isn't defined yet
   type T 
   def doit: T => T
}
2 голосов
/ 29 ноября 2010

Вы можете написать:

trait Foo[T] {
  self:T =>
  def doit(other: T): T
}

case class Bar(name: String) extends Foo[Bar] {
  def doit(other: Bar): Bar = ...
}

Разница в вашем примере в том, что Bar не может быть создан каким-либо другим способом (например, case class Bar(name: String) extends Foo[String]).

1 голос
/ 29 ноября 2010
trait Foo[A <: Foo[A]]

Эта черта может быть смешана только в том случае, если A является подтипом Foo [A] и единственный тип, удовлетворяющий этому, это класс Foo, в который смешивается.Я видел это решение в чертах Mapper в Lift.

1 голос
/ 29 ноября 2010

РЕДАКТИРОВАТЬ - Ниже мой оригинальный ответ.Ваш комментарий указывает, что вы хотите вернуть произвольный экземпляр соответствующего типа, но я не очень верю, что это в любом случае разумно. Предположим, это было с помощью синтаксиса T.type :

trait T { def foo : T.type }

trait U extends T { def foo = new U } //must be a U

class W extends U

val w : W = (new W).foo //oh dear.

Это возможно через this.type:

scala> trait T {
 | def foo : this.type
 | }
defined trait T

scala> class W extends T {
 | def foo  = this
 | }
defined class W

scala> (new W).foo
res0: W = W@22652552

scala> res0.foo
res1: res0.type = W@22652552

И затем также:

scala> ((new W) : T)
res4: T = W@45ea414e

scala> res4.foo.foo.foo
res5: res4.type = W@45ea414e
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...