2014-11-25 15 views
8

Tôi muốn xác định phương thức được chia sẻ bởi tất cả các thành viên của một công đoàn bị phân biệt đối xử. Hiện tại tôi đã thực hiện nó như thế này, nhưng nó có vẻ thực sự không phù hợp - chắc chắn có một cách tốt hơn. Gợi ý?Phương pháp thành viên công đoàn bị phân biệt

type A = 
    {AData:string} 
    member this.SharedMethod (x:float) : int= ... 
type B = 
    {BData:float} 
    member this.SharedMethod (x:float) : int= ... 
type AB = 
| A of A 
| B of B 

let CallSharedMethod (ab:AB) x = 
    match ab with 
    | AB.A(a') -> a'.SharedMethod x 
    | AB.B(b') -> b'.SharedMethod x 
+0

Bạn đang thiếu ràng buộc đối tượng, tức là: this.SharedMethod nếu không nó sẽ không hoạt động. Ngoài ra, bạn cần phải thêm thông tin về phương pháp chia sẻ của bạn với thể hiện của DU (trên thực tế là một loại bản ghi), bởi vì nếu nó không có gì bạn có thể sử dụng một chức năng thường xuyên. Tôi chắc chắn không phải là trường hợp của bạn. – Gustavo

+0

Mùi với tôi như phương pháp nên được trên DU. Nhưng nếu không, bạn có thể sử dụng các bản ghi để thực hiện một giao diện. – Daniel

+0

Có, xin lỗi mã của tôi không chính xác cú pháp chính xác. Tôi quan tâm nhiều hơn đến mô hình- làm cách nào để biểu thị sự thật rằng mỗi loại phụ của DU chia sẻ một tên phương thức chung? Tôi sẽ chỉnh sửa mã để làm cho nó chính xác hơn. –

Trả lời

12

Điều gì tương tự?

type AB = 
    | A of string 
    | B of float 

    member self.SharedMethod (x : float) = 
     match self with 
     | A s -> x 
     | B f -> f + x 

Giả định rằng bạn muốn mỗi biến thể của loại tổng hợp (còn gọi là phân biệt đối xử) để làm điều gì đó khác với thông số nổi.

Đối với trường hợp A, tôi chỉ trả về giá trị ban đầu kể từ khi không có nhiều khác tôi có thể làm gì (vì không có chung mối quan hệ hữu ích giữa stringfloat rằng sản lượng một float).

7

Trong ví dụ của bạn, bạn có tăng cường các kỷ lục loại AB mỗi một thành viên chẳng hạn. Tuy nhiên, bạn không chỉ có thể tăng thêm các loại bản ghi, bạn cũng có thể tăng thêm công đoàn (như được hiển thị trong câu trả lời của @ Rodrick). Nếu bạn làm điều này, tăng cường của công đoàn sẽ được "chia sẻ" bởi mỗi trường hợp DU, đó là những gì bạn đã yêu cầu. Để làm điều này rõ ràng hơn, tôi đã đổi tên một số bộ phận của các ví dụ của bạn:

type A = { AData:string } 
type B = { BData:float } 

type AB = 
    | ACase of A 
    | BCase of B 
    member __.SharedMethod x = 0 

let callSharedMethod (ab:AB) x = ab.SharedMethod x 

Nếu bạn nhìn vào các mã biên dịch trong trình duyệt đối tượng (hoặc một decompiler như ILSpy), bạn sẽ thấy rằng AB được biên dịch như lớp cơ sở của hai lớp con AB.ACaseAB.BCaseSharedMethod thuộc về lớp cơ sở AB.

Xem thêm phần 8.5.1 của số F# 3.0 specification: Thành viên thuộc loại Liên minh.

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