Tôi đang cố gắng tìm một giải pháp thay thế sạch hơn (đó là thành ngữ đối với Scala) với loại điều bạn thấy với ràng buộc dữ liệu trong ràng buộc dữ liệu WPF/silverlight - tức là, triển khai INotifyPropertyChanged. Đầu tiên, một số nền:tài sản thành ngữ đã thay đổi thông báo trong scala?
Trong ứng dụng .Net WPF hoặc Silverlight, bạn có khái niệm liên kết dữ liệu hai chiều (có nghĩa là, ràng buộc giá trị của một phần tử của giao diện người dùng với thuộc tính .net của DataContext trong một cách để thay đổi thành phần UI ảnh hưởng đến thuộc tính và ngược lại Một cách để kích hoạt tính năng này là thực hiện giao diện INotifyPropertyChanged trong DataContext của bạn. . "loại đây là cách nó có thể tìm trong Scala:
trait IDrawable extends INotifyPropertyChanged
{
protected var drawOrder : Int = 0
def DrawOrder : Int = drawOrder
def DrawOrder_=(value : Int) {
if(drawOrder != value) {
drawOrder = value
OnPropertyChanged("DrawOrder")
}
}
protected var visible : Boolean = true
def Visible : Boolean = visible
def Visible_=(value: Boolean) = {
if(visible != value) {
visible = value
OnPropertyChanged("Visible")
}
}
def Mutate() : Unit = {
if(Visible) {
DrawOrder += 1 // Should trigger the PropertyChanged "Event" of INotifyPropertyChanged trait
}
}
}
Vì lợi ích của vũ trụ, chúng ta hãy giả định loại INotifyPropertyChanged là một đặc điểm quản lý một danh sách các callbacks loại (AnyRef, string) => Đơn vị, và OnPropertyChanged là một phương thức gọi tất cả các callbacks đó, truyền "this" như AnyRef và String được truyền vào). Đây chỉ là một sự kiện trong C#.
Bạn có thể thấy ngay vấn đề: đó là một tấn mã soạn sẵn cho hai thuộc tính. Tôi đã luôn muốn viết một cái gì đó như thế này thay vì:
trait IDrawable
{
val Visible = new ObservableProperty[Boolean]('Visible, true)
val DrawOrder = new ObservableProperty[Int]('DrawOrder, 0)
def Mutate() : Unit = {
if(Visible) {
DrawOrder += 1 // Should trigger the PropertyChanged "Event" of ObservableProperty class
}
}
}
tôi biết rằng tôi có thể dễ dàng viết nó như thế này, nếu ObservableProperty [T] có giá trị gia tăng/Value_ = phương pháp (đây là phương pháp tôi đang sử dụng bây giờ):
trait IDrawable {
// on a side note, is there some way to get a Symbol representing the Visible field
// on the following line, instead of hard-coding it in the ObservableProperty
// constructor?
val Visible = new ObservableProperty[Boolean]('Visible, true)
val DrawOrder = new ObservableProperty[Int]('DrawOrder, 0)
def Mutate() : Unit = {
if(Visible.Value) {
DrawOrder.Value += 1
}
}
}
// given this implementation of ObservableProperty[T] in my library
// note: IEvent, Event, and EventArgs are classes in my library for
// handling lists of callbacks - they work similarly to events in C#
class PropertyChangedEventArgs(val PropertyName: Symbol) extends EventArgs("")
class ObservableProperty[T](val PropertyName: Symbol, private var value: T) {
protected val propertyChanged = new Event[PropertyChangedEventArgs]
def PropertyChanged: IEvent[PropertyChangedEventArgs] = propertyChanged
def Value = value;
def Value_=(value: T) {
if(this.value != value) {
this.value = value
propertyChanged(this, new PropertyChangedEventArgs(PropertyName))
}
}
}
Nhưng có cách nào để triển khai phiên bản đầu tiên sử dụng implicits hoặc một số tính năng khác/thành ngữ của Scala để làm cho trường hợp ObservableProperty chức năng như thể chúng là thường xuyên "tài sản" trong scala, mà không cần phải gọi các phương pháp giá trị? Chỉ khác điều tôi có thể nghĩ đến là một cái gì đó như thế này, đó là nhiều tiết hơn một trong hai phiên bản trên, nhưng vẫn còn ít tiết so với bản gốc:
trait IDrawable {
private val visible = new ObservableProperty[Boolean]('Visible, false)
def Visible = visible.Value
def Visible_=(value: Boolean): Unit = { visible.Value = value }
private val drawOrder = new ObservableProperty[Int]('DrawOrder, 0)
def DrawOrder = drawOrder.Value
def DrawOrder_=(value: Int): Unit = { drawOrder.Value = value }
def Mutate() : Unit = {
if(Visible) {
DrawOrder += 1
}
}
}
Bài báo này có thể bạn quan tâm: http://www.ganguin.net/frp2d.pdf –
Xem thêm http: // stackoverflow.com/questions/1054179/functional-reactive-programming-in-scala Không thành công cho đến nay. Thật không may, đây là một quyết định thiết kế tồi tệ ở Scala. – thSoft