2013-04-05 33 views
17

F # có tính năng được gọi là "Type extension" mang đến khả năng của nhà phát triển để mở rộng các loại hiện có. Có hai loại tiện ích mở rộng: tiện ích nội tạitiện ích mở rộng tùy chọn. Đầu tiên là tương tự như một phần loại trong C# và thứ hai là một cái gì đó tương tự như phần mở rộng phương pháp (nhưng mạnh hơn).Loại tiện ích mở rộng và thành viên hiển thị trong F #

Để sử dụng tiện ích mở rộng nội tại, chúng tôi nên đặt hai khai báo vào cùng một tệp. Trong trường hợp này trình biên dịch sẽ hợp nhất hai định nghĩa thành một loại cuối cùng (tức là đây là hai "phần" của một loại).

Vấn đề là hai loại có quy tắc truy cập khác nhau cho các thành viên và các giá trị khác nhau:

// SampleType.fs 
// "Main" declaration 
type SampleType(a: int) = 
    let f1 = 42 
    let func() = 42 

    [<DefaultValue>] 
    val mutable f2: int 
    member private x.f3 = 42 
    static member private f4 = 42 

    member private this.someMethod() = 
     // "Main" declaration has access to all values (a, f1 and func()) 
     // as well as to all members (f2, f3, f4) 
     printf "a: %d, f1: %d, f2: %d, f3: %d, f4: %d, func(): %d" 
      a f1 this.f2 this.f3 SampleType.f4 (func()) 

// "Partial" declaration 
type SampleType with 

    member private this.anotherMethod() = 
     // But "partial" declaration has no access to values (a, f1 and func()) 
     // and following two lines won't compile 
     //printf "a: %d" a 
     //printf "f1: %d" f1 
     //printf "func(): %d" (func()) 

     // But has access to private members (f2, f3 and f4) 
     printf "f2: %d, f3: %d, f4: %d" 
      this.f2 this.f3 SampleType.f4 

tôi đọc F # đặc điểm kỹ thuật nhưng không tìm thấy bất kỳ ý tưởng tại sao F # biên dịch phân biệt giữa tờ khai giá trị và thành viên.

Trong 8.6.1.3 section của F # đặc tả nói rằng "Các chức năng và các giá trị được xác định bởi định nghĩa ví dụ là lexically scoped (và do đó ngầm tư nhân) cho các đối tượng được xác định.". Khai báo từng phần có tất cả quyền truy cập vào tất cả các thành viên riêng (tĩnh và cá thể). Tôi đoán là bởi các tác giả đặc điểm kỹ thuật "phạm vi từ vựng" cụ thể chỉ có nghĩa là tuyên bố "chính" nhưng hành vi này có vẻ lạ đối với tôi.

Câu hỏi đặt ra là: hành vi này có chủ ý và lý do gì đằng sau nó?

Trả lời

10

Đây là một câu hỏi hay! Như bạn đã chỉ ra, đặc điểm kỹ thuật nói rằng "giá trị cục bộ là lexically scoped đối tượng đang được xác định", nhưng nhìn vào đặc tả F #, nó không thực sự xác định phạm vi từ vựng có nghĩa là gì trong trường hợp này.

Khi mẫu của bạn hiển thị, hành vi hiện tại là phạm vi từ vựng của định nghĩa đối tượng chỉ là định nghĩa loại chính (không bao gồm phần mở rộng nội tại). Tôi không quá ngạc nhiên bởi điều đó, nhưng tôi thấy rằng cách giải thích khác cũng có ý nghĩa ...

Tôi nghĩ một lý do chính đáng cho việc này là hai loại tiện ích mở rộng sẽ hoạt động giống nhau (nhiều nhất có thể) và bạn sẽ có thể cấu trúc lại mã của bạn bằng cách sử dụng mã này để sử dụng mã khác khi bạn cần. Hai loại chỉ khác nhau về cách chúng được biên soạn dưới trang bìa. Thuộc tính này sẽ bị hỏng nếu một loại cho phép truy cập vào phạm vi từ vựng trong khi loại kia không (vì, thành viên mở rộng về mặt kỹ thuật không thể thực hiện điều đó).

Điều đó nói rằng, tôi nghĩ rằng điều này có thể được (ít nhất) được làm rõ trong đặc điểm kỹ thuật. Cách tốt nhất để báo cáo điều này là gửi email đến fsbugs tại microsoft dot com.

+2

Tôi nhận được điểm của bạn về sự giống nhau giữa hai loại tiện ích mở rộng loại. Nhưng hành vi của các phần mở rộng * nội tại * và * tùy chọn * khác nhau: các phần mở rộng tùy chọn chỉ có thể truy cập vào bề mặt công khai của kiểu mở rộng nhưng phần mở rộng nội tại vẫn có quyền truy cập vào các thành viên riêng và được bảo vệ mở rộng. Vì vậy, họ cũng có ngữ nghĩa khác nhau, không chỉ cách họ biên soạn dưới trang bìa. –

+0

@SergeyTeplyakov Hmm, đó là một điểm tốt. Bạn nói đúng là chúng khác nhau ở khía cạnh này. Tôi cho rằng điểm then chốt là định nghĩa của "phạm vi từ vựng" trong ngữ cảnh này (rõ ràng là thiếu trong đặc tả F #). –

+0

Cảm ơn, Tomas. Tôi nghĩ bạn đúng về phạm vi từ vựng. Quan điểm của tôi là, một phần các loại trong C# nổi tiếng và được sử dụng rộng rãi tính năng cho các nhà thiết kế hỗ trợ. Nhưng với loại hạn chế như vậy, chúng tôi không thể xử lý phần mở rộng nội tại như tuyên bố loại một phần đầy đủ tính năng. Và điều này có nghĩa là chúng tôi không thể nhận được bất kỳ hỗ trợ thiết kế nào (đối với WinForms và WPF) cho đến khi các phần mở rộng nội tại có những hạn chế như vậy. –

3

tôi đã gửi câu hỏi này đến fsbugs tại microsoft dot com và nhận được câu trả lời từ sau Don Syme:

Hi Sergey,

Vâng, hành vi này là có chủ ý. Khi bạn sử dụng "let" trong phạm vi lớp, mã định danh có phạm vi từ vựng theo định nghĩa kiểu. Giá trị thậm chí có thể không được đặt trong một trường - ví dụ nếu một giá trị không được bắt bởi bất kỳ phương thức nào thì nó sẽ trở thành cục bộ cho hàm tạo. Phân tích này được thực hiện cục bộ cho lớp.

Tôi hiểu rằng bạn mong đợi tính năng này hoạt động như các lớp một phần trong C#. Tuy nhiên, nó không hoạt động theo cách đó.

Tôi nghĩ thuật ngữ "phạm vi từ vựng" nên được xác định rõ ràng hơn trong thông số, bởi vì nếu không hành vi hiện tại cũng sẽ gây ngạc nhiên cho các nhà phát triển khác.

Rất cám ơn Don đã trả lời!

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