2016-11-29 3 views
0

Я пытаюсь определить базовый признак, используемый для простой системы CRUD. Тем не менее, мне нужна базовая черта для поддержки «copyWithId» def (поскольку маска класса case Scala для копирования недоступна). Лучший подход, который я нашел до сих пор:Определение определения scala trait, которое возвращает конкретный экземпляр подтипа

trait Identifiable[ID, T] { 
    def id: Option[ID] 
    def copyWithId(id: Option[ID]): T 
} 

case class TestNamedIdentity(id: Option[Int], name: String) 
    extends Identifiable[Int, TestNamedIdentity] { 

    def copyWithId(id: Option[Int]): TestNamedIdentity = { 
    copy(id = id) 
    } 
} 

Это работает, но выглядит немного неуклюжим, потому что он требует, чтобы все конкретных случаев, чтобы продлить с ID и Самостью. Я хотел бы написать примерно следующее:

trait Identifiable[ID] { 
    this:X => 
    def copyWithId(id: Option[ID]): X 
    def id: Option[ID] 
} 

Использование некоторой формы самостоятельной ссылки на конкретный класс. Любой способ сделать эту работу?

Update: С использованием случае ниже

Идея заключается в том, чтобы использовать его в коде как

abstract class SomeClass[A <: IdentifiableEntity[ID], ID] { 
    def someFunc2: Option[ID] 
    def someFunc(item: A): A = { 
    item.copyWithId(someFunc2) 
    } 
} 

Использование раствора из @jwvh требует «asInstanceOf» отливку после вызова. Что для моего случая использования работает, но надеялся на более элегантное решение.

item.copyWithId(someFunc2).asInstanceOf[A] 
+1

Первый вид, который я знаю, хорошо работает, когда нужно написать параметрический метод, включающий «Идентифицируемый», который также возвращает «T». Повторное копирование методов копирования кажется неуклюжим, но, делая то же самое с методами CRUD, я думал, что это хуже, поэтому я справился с этим. Кроме того, лучшее, что я мог придумать, чтобы сохранить некоторый шаблон, было бы макросом, но это только спасло бы столько. Работа с «копией» абстрактным образом довольно сложна. –

+0

@MichaelZajac Я боялся, что макрос будет единственным жизнеспособным решением, и я не хочу добавлять этот уровень замешательства в кодовую базу. Я думаю, что подход jwvh по крайней мере чище для потребителя api, чем моя первая форма выше. – rapidninja

ответ

1

похоже, что сработало.

trait Identifiable[ID] { 
    def id: Option[ID] 
    def copyWithId(id: Option[ID]): Identifiable[ID] 
} 

Тогда класс корпуса упрощен.

case class TestNamedIdentity(id: Option[Int], name: String 
          ) extends Identifiable[Int] { 
    def copyWithId(id: Option[Int]): TestNamedIdentity = copy(id = id) 
} 
+0

Это действительно работает, однако для этого требуется любое использование для отбрасывания. Например: 'saved.copyWithId (id) .asInstanceOf [A]'. Таким образом, в основном торговля одним шаблоном для другого. Для конкретного случая использования я работаю с этими работами. Спасибо – rapidninja

+1

@rapidninja, я этого не вижу. Тип результата 'copyWithId()' такой, как определено в классе case. Почему требуется кастинг? Является ли 'saved.copyWithId()' предполагаемым для другого типа, чем 'saved'? – jwvh

+0

Я добавил пример в исходное сообщение, чтобы объяснить случай использования и почему требуется кастинг. – rapidninja

Смежные вопросы