2016-06-04 16 views
5

Tôi đang cố gắng tạo một đoạn mã nhỏ trong F #. Ý tưởng là tôi sẽ có một giao diện xác định một vài phương thức, thuộc tính và sự kiện. Sử dụng giao diện này, tôi muốn định nghĩa một lớp trừu tượng (có một kiểu generic) sẽ thực hiện một số thuộc tính/phương thức nhưng không phải tất cả các thành viên được định nghĩa trong giao diện. Trách nhiệm để xác định tất cả các thành viên sẽ được trên các lớp học có nguồn gốc.Giao diện và lớp trừu tượng trong F #

Cho đến giờ tôi bị kẹt với giao diện và lớp trừu tượng. Những vấn đề tôi đang gặp:

  • Định nghĩa lớp trừu tượng không nhận ra định nghĩa giao diện
  • Tôi không chắc chắn cách định nghĩa các thành viên trừu tượng cho giao diện trong lớp trừu tượng

Giao diện biên dịch tốt nhưng lớp trừu tượng có nhiều lỗi. Các thông điệp được bao gồm trong mã số

Tất cả nhận xét, chỉnh sửa, gợi ý, v.v. Vì đây là thử nghiệm đầu tiên của tôi trên F #, có lẽ có rất nhiều lỗi để chỉ ra.

Code tôi có cho đến nay

định nghĩa giao diện

namespace A 
    type IValueItem = 
     interface  
      [<CLIEvent>] 
      abstract member PropertyChanged : 
       Control.IEvent<System.ComponentModel.PropertyChangedEventHandler, 
           System.ComponentModel.PropertyChangedEventArgs> 

      abstract ConvertedX : double with get, set 

      abstract Y : double with get, set 

      abstract member CreateCopy : obj 

      abstract member NewTrendItem : obj 
     end 

Và lớp trừu tượng

namespace A 
    [<AbstractClass>] 
    type ValueItem<'TX>() = 

     [<DefaultValue>] 
     val mutable _y : double 

     let _propertyChanged = new Event<_>() 

     // ERROR: This type is not an interface type 
     // ERROR: The type 'obj' is not an interface type 
     // ERROR: The type 'IValueItem' is not defined 
     interface IValueItem with 

      // ERRROR No abstract or interface member was found that corresponds to this override 
      [<CLIEvent>] 
      member this.PropertyChanged : 
        Control.IEvent<System.ComponentModel.PropertyChangedEventHandler, 
            System.ComponentModel.PropertyChangedEventArgs> 
       = _propertyChanged.Publish 

      // This definition is incomplete, should be abstract 
      member ConvertedX : double with get, set 

      // ERROR: Incomplete structured construct at or before this point in pattern 
      member CreateCopy() : obj 

      member NewTrendItem() : obj 

     abstract X : 'TX with get, set 

     member this.Y 
      with get() = this._y 
      and set(value) = 
       if this._y <> value then 
        this._y <- value 
        this.NotifyPropertyChanged("Y") 

     member this.NotifyPropertyChanged(propertyName) = 
       this.PropertyChanged.Trigger(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)) 

Trả lời

7

Định nghĩa lớp trừu tượng không nhận ra định nghĩa giao diện

Giao diện phải là declared above lớp trừu tượng, hoặc: trong một dự án/assembly được tham chiếu, trong tệp phía trên tệp hiện tại của bạn (thứ tự các tệp quan trọng) hoặc cao hơn trong cùng một tệp.

Tôi không chắc chắn làm thế nào để xác định các thành viên trừu tượng cho giao diện trong lớp trừu tượng

Đáng tiếc là chúng ta phải thực hiện tất cả các thành viên của giao diện, để giữ cho các hành vi bạn muốn, bạn có thể có cuộc gọi thực hiện một thành viên trừu tượng của lớp đó có chữ ký giống nhau:

type IValueItem = 
    [<CLIEvent>] 
    abstract PropertyChanged : 
     Control.IEvent<System.ComponentModel.PropertyChangedEventHandler, 
         System.ComponentModel.PropertyChangedEventArgs> 

    abstract ConvertedX : double with get, set 

    abstract Y : double with get, set 

    abstract CreateCopy : obj 

    abstract NewTrendItem : obj 

[<AbstractClass>] 
type ValueItem<'TX>() = 
    let mutable y = 0.0 

    let propertyChanged = Event<_, _>() 

    interface IValueItem with 

     [<CLIEvent>] 
     member __.PropertyChanged : Control.IEvent<_, _> = propertyChanged.Publish 

     member this.ConvertedX 
      with get() = this.ConvertedX 
      and set(x) = this.ConvertedX <- x 

     member this.CreateCopy = this.CreateCopy 
     member this.NewTrendItem = this.NewTrendItem 

     member this.Y 
      with get() = this.Y 
      and set(y) = this.Y <- y 

    abstract ConvertedX : double with get, set 
    abstract CreateCopy : obj 
    abstract NewTrendItem : obj 

    member this.Y 
     with get() = y 
     and set(value) = 
      if y <> value then 
       y <- value 
       this.NotifyPropertyChanged("Y") 

    abstract X : 'TX with get, set 

    member this.NotifyPropertyChanged(propertyName) = 
     propertyChanged.Trigger(this, System.ComponentModel.PropertyChangedEventArgs(propertyName)) 

thuộc tính Y được định nghĩa hai lần mà trông hơi kỳ lạ lúc đầu. Việc triển khai giao diện ngăn cản việc triển khai trên lớp - điều này có nghĩa là để truy cập Y bạn sẽ không cần phải upcast một lớp của giao diện, tôi đã thực hiện điều này để duy trì hành vi tương tự như ví dụ ban đầu của bạn

để bình luận của bạn:

để có được một thành viên ảo trên class abstract bạn cần phải khai báo thành viên như tóm tắt và cung cấp một cài đặt mặc định, đây là một ví dụ để phù hợp với mã trong bình luận của bạn:

type IValueItem = 
    abstract NewTrendItem : unit -> obj 

[<AbstractClass>] 
type ValueItem<'TX>() = 
    interface IValueItem with 
     member this.NewTrendItem() = this.NewTrendItem() 

    abstract NewTrendItem : unit -> obj 
    default __.NewTrendItem() = null 

type NumberItem() = 
    inherit ValueItem<double>() 

    override __.NewTrendItem() = new NumberItem() :> obj 

Nói chung OO F # được sử dụng để tương tác với phần còn lại của.NET thế giới - trông giống như trường hợp ở đây. Nhưng nếu mã không tương tác với .NET API khác yêu cầu giao diện OO, bạn có thể thấy việc mô hình hoá vấn đề với phương pháp tiếp cận chức năng có thể dẫn đến một số mã sạch hơn. OO trong F # có thể không tạo ấn tượng ban đầu tốt về ngôn ngữ (mặc dù cá nhân tôi rất thích sự giải thích và ngắn gọn về nó)

+0

Cảm ơn sự giúp đỡ của bạn. Tôi vẫn chỉ bị mắc kẹt với sự thừa kế và trọng tài của các phương pháp. Lớp trừu tượng bây giờ định nghĩa 'thành viên this.NewTrendItem() = null' và lớp dẫn xuất trông giống như' type NumberItem() = kế thừa ValueItem () ...... ghi đè this.NewTrendItem() = new NumberItem () '. Tuy nhiên, tôi nhận được _Không tìm thấy thành viên trừu tượng hoặc giao diện nào tương ứng với lỗi override_ này. – user6423491

+0

Không có vấn đề, hy vọng nó giúp đỡ. Tôi đã cập nhật nhận xét để cung cấp ví dụ về cách bạn có thể làm điều đó. –

Các vấn đề liên quan