Если Ваш SQL Server использования, 2005 и выше Вас может создать снимок базы данных, который позволит Вам откатывать любые изменения, внесенные в момент времени снимка.
Я не уверен, будет ли это действительно полезно для вас, но самое близкое, что я могу придумать, - это this.type
. Например:
scala> class A { val l: List[this.type] = Nil }
defined class A
scala> new A().l
res3: List[A] = List()
scala> class B extends A
defined class B
scala> new B().l
res4: List[B] = List()
Ключевое слово this
в Scala более или менее эквивалентно.
При разработке расширяемого программного обеспечения иногда бывает удобно объявить тип значения this
явно:
Явно типизированные ссылки на себя в Scala
http://www.scala-lang.org/node/124
Типы однокнопочных и ETSR не решают проблему. Я сам искал такую же возможность в Scala, но, видимо, в ней отсутствует так называемая аннотация самотипа.
Есть обстоятельства, при которых такие самотипные аннотации могли бы быть очень полезны. Рассмотрим пример (адаптированный из Circular type parameters question example):
// we want a container that can store elements
trait Container[E <: Element[E]] {
def elements: Seq[E]
def add(elem: E): Unit
}
// we want elements be aware of their enclosing container
trait Element[E <: Element[E]] {
def container: Container[E]
}
Предположим, вы поместили его в библиотеку. Потребитель библиотеки должен сделать следующее:
object PersonContainer extends Container[Person] {
// actual implementation is not important
def elements = Nil
def add(p: Person) = {}
}
class Person extends Element[Person] { // {1}
def container = PersonContainer
}
Все в порядке и все работает так, как и ожидалось. Единственное, что касается потребителя библиотеки, это то, что supposed должен использовать параметр типа self-bound (#1 в коде). Но это еще не все. Теперь предположим, что вы имеете в виду какой-то паттерн ActiveRecord и хотите добавить метод save
к Element
, который просто делегирует ему метод контейнера add
. Удивительно, но это не так просто:
trait Element[E <: Element[E]] {
def container: Container[E]
def save() = container.add(this) // won't compile
}
found : Element[E]
required: E
Интуитивно, у нас есть несколько вариантов:
добавить
метод принять Element[E]
вместо E
; этот
в Element[E]
. Ни один из этих вариантов не является удовлетворительным только потому, что E
не совпадает с Element[E]
(реализации не принуждают использовать параметры типа self-bound). Единственное, что я вижу в решении этой проблемы - это наличие концепции типа self-type в Scala (допустим, она есть в нашем любимом языке):
trait Container[E <: Element] {
def elements: Seq[E]
def add(elem: E): Unit
}
trait Element { // the type parameter would be redundant ...
def save() = container.add(this) // ... and this would be possible, too, ...
def container: Container[this] // ... if only we could do this
}
Если бы компилятор мог трактовать this
(или, может быть, другое ключевое слово), когда он используется внутри квадратных скобок, как тип действительной реализации (т.е. как тип в результате obj.getClass
), то проблемы исчезли бы.
P.S. Может ли кто-нибудь подумать о включении этого материала в список желаний Scala? К сожалению, я не знаю, как сложно реализовать такую логику, так как могут возникнуть проблемы с пресловутым стиранием JVM.
P.P.S. Или, может быть, есть другой Scala-путь, о котором я не знаю?