Tại sao .NET framework không có khái niệm về các lớp như các loại hạng nhất?


20

Những người quen thuộc với lịch sử đã biết rằng C # và .NET framework khởi đầu về cơ bản là "Delphi viết lại để cảm thấy giống như Java", được kiến ​​trúc sư trưởng đằng sau Delphi, Anders Hejlsberg thiết kế. Mọi thứ đã thay đổi khá nhiều kể từ đó, nhưng ban đầu về những điểm tương đồng rõ ràng đến mức thậm chí còn có một số suy đoán nghiêm trọng rằng .NET thực sự là sản phẩm ban đầu của Borland.

Nhưng gần đây tôi đã xem xét một số công cụ .NET và một trong những tính năng thú vị và hữu ích nhất từ ​​Delphi dường như bị thiếu hoàn toàn: khái niệm các lớp như một kiểu dữ liệu hạng nhất. Đối với những người không quen thuộc với nó, loại TClassđại diện cho một tham chiếu đến một lớp, tương tự như Typeloại trong .NET. Nhưng trong đó .NET sử dụng Typeđể phản chiếu, Delphi sử dụng TClassnhư một phần tích hợp rất quan trọng của ngôn ngữ. Nó cho phép các thành ngữ hữu ích khác nhau đơn giản là không tồn tại và không tồn tại mà không có nó, chẳng hạn như các biến kiểu con lớp và phương thức lớp ảo.

Mỗi ngôn ngữ OO đều có các phương thức ảo, trong đó các lớp khác nhau thực hiện cùng một khái niệm cơ bản của một phương thức theo các cách khác nhau và sau đó phương thức đúng được gọi trong thời gian chạy dựa trên loại thực tế của đối tượng mà nó được gọi. Delphi mở rộng khái niệm này cho các lớp: nếu bạn có một tham chiếu TClass được định nghĩa là một kiểu con lớp cụ thể (nghĩa class of TMyClasslà biến đó có thể chấp nhận bất kỳ tham chiếu lớp nào kế thừa từ TMyClass, nhưng không phải bất cứ thứ gì bên ngoài quyền thừa kế ) có các phương thức ảo phạm vi lớp được đính kèm nó, chúng có thể được gọi mà không cần một thể hiện bằng cách sử dụng kiểu thực tế của lớp. Áp dụng mô hình này cho các nhà xây dựng làm cho việc triển khai Factory trở nên tầm thường, chẳng hạn.

Dường như không có gì tương đương trong .NET. Với sự hữu ích như các tham chiếu lớp (và đặc biệt là các hàm tạo ảo và các phương thức lớp ảo khác!), Có ai nói gì về lý do tại sao chúng bị bỏ đi không?

Ví dụ cụ thể

Hình thức khử lưu huỳnh

Delphi VCL lưu các biểu mẫu ở DFMđịnh dạng, DSL để mô tả phân cấp thành phần. Khi trình đọc biểu mẫu phân tích dữ liệu DFM, nó sẽ chạy trên các đối tượng được mô tả như sau:

object Name: ClassName
   property = value
   property = value
   ...
   object SubObjectName: ClassName
      ...
   end
end

Điều thú vị ở đây là ClassNamemột phần. Mỗi lớp thành phần đăng ký TClassvới hệ thống truyền phát thành phần tại initializationthời điểm (nghĩ rằng các hàm tạo tĩnh, chỉ khác nhau một chút, được đảm bảo xảy ra ngay khi khởi động.) Điều này đăng ký mỗi lớp trong một chuỗi -> hàm băm TClass với tên lớp là khóa.

Mỗi thành phần xuất phát từ TComponent, có một hàm tạo ảo lấy một đối số duy nhất , Owner: TComponent. Bất kỳ thành phần nào cũng có thể ghi đè lên hàm tạo này để cung cấp cho việc khởi tạo riêng của nó. Khi trình đọc DFM đọc một tên lớp, nó sẽ tìm tên trong hàm băm đã nói ở trên và lấy tham chiếu lớp tương ứng (hoặc đưa ra một ngoại lệ nếu nó không có ở đó), sau đó gọi hàm tạo TComponent ảo trên đó, được biết là tốt bởi vì hàm đăng ký lấy tham chiếu lớp được yêu cầu để xuống từ TComponent và bạn kết thúc với một đối tượng thuộc loại thích hợp.

Thiếu điều này, tương đương WinForms là ... à ... một mớ hỗn độn lớn để nói thẳng ra, đòi hỏi bất kỳ ngôn ngữ .NET mới nào phải thực hiện lại hoàn toàn việc xê-ri hóa hình thức của chính nó. Điều này hơi gây sốc khi bạn nghĩ về nó; vì toàn bộ quan điểm của việc có CLR là cho phép nhiều ngôn ngữ sử dụng cùng một cơ sở hạ tầng cơ bản, nên một hệ thống kiểu DFM sẽ có ý nghĩa hoàn hảo.

Khả năng mở rộng

Một lớp trình quản lý hình ảnh mà tôi đã viết có thể được cung cấp một nguồn dữ liệu (chẳng hạn như đường dẫn đến tệp hình ảnh của bạn) và sau đó tự động tải các đối tượng hình ảnh mới nếu bạn cố truy xuất một tên không có trong bộ sưu tập nhưng có sẵn trong nguồn dữ liệu. Nó có một biến lớp được gõ là class oflớp hình ảnh cơ sở, đại diện cho lớp của bất kỳ đối tượng mới nào sẽ được tạo. Nó đi kèm với một mặc định, nhưng có một số điểm, khi tạo hình ảnh mới với mục đích đặc biệt, rằng hình ảnh nên được thiết lập theo những cách khác nhau. (Tạo kênh không có kênh alpha, truy xuất siêu dữ liệu đặc biệt từ tệp PNG để chỉ định kích thước sprite, v.v.)

Điều này có thể được thực hiện bằng cách viết một lượng lớn mã cấu hình và chuyển các tùy chọn đặc biệt cho tất cả các phương thức có thể tạo ra một đối tượng mới ... hoặc bạn chỉ có thể tạo một lớp con của lớp hình ảnh cơ sở ghi đè lên một phương thức ảo trong đó khía cạnh trong câu hỏi được cấu hình, và sau đó sử dụng khối try / cuối cùng để thay thế tạm thời thuộc tính "lớp mặc định" khi cần và sau đó khôi phục nó. Làm điều đó với các biến tham chiếu lớp đơn giản hơn nhiều và không phải là điều có thể được thực hiện với generic.



3
Bạn có thể cung cấp một hoặc hai ví dụ cụ thể trong đó a TClasslà hữu ích, với một số mã mẫu? Trong nghiên cứu về internet của tôi TClass, tôi thấy rằng nó TClasscó thể được truyền qua như một tham số. Điều này được thực hiện trong .NET bằng Generics. Các phương thức Factory được đánh dấu đơn giản staticbằng .NET và không yêu cầu một thể hiện lớp để thực thi.
Robert Harvey

7
@RobertHarvey: Đối với cá nhân tôi, C # bắt đầu có ý nghĩa hơn rất nhiều khi tôi ngừng nhìn vào nó khi Java / C ++ tải lại và bắt đầu coi nó là Modula-2 với các đối tượng. Nó giống với Java: mọi người đều nói nó bị ảnh hưởng bởi C ++, nhưng điều đó không đúng. Ảnh hưởng chính của nó là Objective-C (và Smalltalk thông qua đó) và Java sẽ có ý nghĩa hơn rất nhiều khi bạn coi nó là Smalltalk với các loại thay vì C ++ với GC.
Jörg W Mittag

3
@RobertHarvey: TClasslà một tính năng ngôn ngữ cơ bản yêu cầu hỗ trợ trình biên dịch. Bạn không thể "tự viết" mà không viết ngôn ngữ của riêng mình và đối với .NET thậm chí điều đó là không đủ vì mô hình đối tượng được xác định bởi CLR, không phải bởi các ngôn ngữ riêng lẻ. Đó là thứ gì đó thực sự cần phải là một phần của chính .NET framework, hoặc nó không thể tồn tại.
Mason Wheeler

4
Trước hết, tôi có thể nói chắc chắn rằng .NET ban đầu không phải là sản phẩm "Borland". Làm thế nào để tôi biết điều này? Tôi đã (vẫn là) một phần của nhóm nòng cốt ban đầu phát triển Delphi. Tôi đã làm việc chặt chẽ với Anders, Chuck, Gary và những người khác. Tất nhiên, tôi chắc chắn rằng bạn biết điều này. Đối với sự tồn tại của một tham chiếu lớp (như TClass và các cấu trúc tương tự được gọi) trong .NET có thể được coi là không cần thiết do sự tồn tại của thông tin loại có thể truy cập thời gian chạy phong phú. Delphi có ít thông tin loại ban đầu và giới thiệu lớp là một sự thỏa hiệp.
Allen Bauer

Câu trả lời:


5

.NET (CLR) là thế hệ thứ ba của Mô hình đối tượng thành phần (COM) của Microsoft, trong những ngày đầu được gọi là "COM + runtime". Microsoft Visual Basic và thị trường điều khiển COM / ActiveX có ảnh hưởng nhiều hơn đến các lựa chọn tương thích kiến ​​trúc CLR cụ thể so với Borland Delphi. (Phải thừa nhận rằng Delphi đã áp dụng các điều khiển ActiveX chắc chắn đã giúp phát triển hệ sinh thái ActiveX, nhưng COM / ActiveX đã tồn tại trước Delphi)

Kiến trúc của COM đã được thực hiện trong C (không phải C ++) và tập trung vào các giao diện, thay vì các lớp. Hơn nữa, thành phần đối tượng được hỗ trợ, có nghĩa là trên thực tế một đối tượng COM có thể được tạo thành từ nhiều đối tượng khác nhau, với giao diện IUn Unknown liên kết chúng lại với nhau. Nhưng IUn Unknown không có vai trò trong việc tạo đối tượng COM, được thiết kế độc lập với ngôn ngữ nhất có thể. Việc tạo đối tượng thường được xử lý bởi IClassFactory và phản ánh bởi ITypeL Library và các giao diện liên quan. Sự tách biệt mối quan tâm này không phụ thuộc vào ngôn ngữ triển khai và các tính năng của từng giao diện COM cốt lõi được giữ ở mức tối thiểu và trực giao.

Vì vậy, do sự phổ biến của các điều khiển COM và ActiveX, kiến ​​trúc .NET đã được xây dựng để hỗ trợ trên COM IUn Unknown, IClassFactory và ITypeL Library. Trong COM, các giao diện này không nhất thiết phải nằm trên cùng một đối tượng, do đó, việc kết hợp chúng lại với nhau không nhất thiết phải có ý nghĩa.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.