2009-05-05 44 views
36

Gần đây tôi đã gặp phải sự cố trong đó có vẻ như tôi cần phương pháp 'tóm tắt tĩnh'. Tôi biết tại sao điều đó là không thể, nhưng làm thế nào tôi có thể làm việc xung quanh giới hạn này?C#, triển khai 'tóm tắt tĩnh' như các phương pháp

Ví dụ: tôi có lớp trừu tượng có chuỗi mô tả. Kể từ chuỗi này là chung cho tất cả các trường hợp, nó được đánh dấu là tĩnh, nhưng tôi muốn yêu cầu tất cả các lớp thừa kế từ lớp này cung cấp thuộc tính Mô tả riêng của họ vì vậy tôi đánh dấu nó như là trừu tượng:

abstract class AbstractBase 
{ 
    ... 
    public static abstract string Description{get;} 
    ... 
} 

Nó sẽ không biên dịch tất nhiên. Tôi đã nghĩ đến việc sử dụng giao diện nhưng giao diện có thể không chứa chữ ký phương thức tĩnh.

Tôi có nên đơn giản là không tĩnh và luôn nhận được một cá thể để có được thông tin cụ thể về lớp học đó không?

Bất kỳ ý tưởng nào?

+0

Tương tự như câu hỏi này http://stackoverflow.com/questions/763344/c-virtual-or-abstract-static-methods/763364#763364 –

+0

Bản sao có thể có của [Tại sao tôi không thể có phương pháp tĩnh trừu tượng trong C# ?] (https://stackoverflow.com/questions/3284/why-cant-i-have-abstract-static-methods-in-c) –

+0

Bản sao có thể có của [Cách triển khai các thuộc tính tĩnh ảo?] (https://stackoverflow.com/questions/15346631/how-to-implement-virtual-static-properties) – peterh

Trả lời

5

Kết hợp tĩnh và trừu tượng có phần vô nghĩa, vâng. Ý tưởng đằng sau tĩnh là một trong những nhu cầu không thể hiện một thể hiện của lớp để sử dụng các thành viên trong câu hỏi; tuy nhiên với trừu tượng, người ta mong đợi một cá thể là một lớp dẫn xuất cung cấp một sự thực thi cụ thể.

Tôi có thể thấy lý do tại sao bạn muốn loại kết hợp này, nhưng thực tế là tác dụng duy nhất sẽ là từ chối việc sử dụng thực hiện 'this' hoặc bất kỳ thành viên không tĩnh nào. Tức là, lớp cha sẽ chỉ ra một hạn chế trong việc thực hiện lớp dẫn xuất, mặc dù không có sự khác biệt cơ bản giữa việc gọi một thành phần trừu tượng hoặc 'trừu tượng tĩnh' (vì cả hai sẽ cần một cá thể cụ thể để tìm hiểu cách triển khai thực hiện)

+0

Tôi đã nghĩ lại tình huống này, và tôi nói đó là sự thật ... chuỗi trừu tượng công khai {get;} ngụ ý giống như chuỗi công khai {get {return "Izeeeeeeeeh";}} là đủ cụ thể. – Calmarius

+71

Nó không vô nghĩa. Hãy tưởng tượng rằng bạn đang thiết kế một khuôn khổ. Bạn yêu cầu các lớp đó triển khai ISomething để lộ một số dữ liệu đã biết trong thời gian biên dịch. Ví dụ: "tên lớp thân thiện". Bạn muốn trình biên dịch đảm bảo rằng tất cả các ISomethings đều có thuộc tính này. Nếu bạn muốn làm điều đó ngay bây giờ, thì bạn phải sử dụng các đặc tính cá thể. Có nghĩa là tạo một thể hiện, thay vì chỉ truy vấn kiểu. Điều đó thật tệ. –

+3

Tôi đồng ý với @RyanBarrett, về thiết kế khung, có thể hữu ích để buộc người tiêu dùng cung cấp một hàm trong lớp dẫn xuất, nhưng cũng cho biết rằng hàm được thực thi tĩnh, không có một cá thể nào. –

31

Bạn không thể.

Nơi để làm điều này là với Thuộc tính.

Ví dụ

[Name("FooClass")] 
class Foo 
{ 
} 
+0

Thông minh. . . – Shog9

+3

Thật vậy ... người ta có thể có thuộc tính Mô tả tĩnh công cộng nhận giá trị thuộc tính mặc dù làm cho nó dễ truy cập hơn ... –

+0

Sẽ được quan tâm để biết cách hoạt động trong thời gian chạy. Liệu các thuộc tính kết thúc như là một ví dụ var bằng cách nào đó? Tôi đã đọc thuộc tính tùy chỉnh trước khi thông qua phản ánh, nhưng không biết làm thế nào CLR xử lý chúng –

3

Nó không phải tĩnh nếu nó phải được gọi là trên một ví dụ.

Nếu bạn không gọi nó trên một trường hợp, thì không có tính đa hình khi chơi (tức là ChildA.Description hoàn toàn không liên quan đến ChildB.Description theo như ngôn ngữ có liên quan).

5

Nếu nó là tĩnh, chỉ có một thể hiện của biến, tôi không thấy làm thế nào thừa kế sẽ có ý nghĩa nếu chúng ta có thể làm những gì bạn muốn thực hiện với tĩnh vars trong các lớp học có nguồn gốc. Cá nhân tôi nghĩ rằng bạn đang đi xa để cố gắng tránh một ví dụ var.

Tại sao không chỉ là cách cổ điển?

abstract class AbstractBase 
{ 
    protected string _Description = "I am boring abstract default value"; 
} 

class Foo : AbstractBase { 

    public Foo() { 
     _Description = "I am foo!"; 
    } 
} 
5

Nếu bạn không nhớ trì hoãn để triển khai thực hiện một cách hợp lý các tài sản mô tả, bạn chỉ có thể làm

public abstract string ClassDescription {get; } 
// ClassDescription is more intention-revealing than Description 

Và các lớp học thực hiện sẽ làm một cái gì đó như thế này:

static string classDescription="My Description for this class"; 
override string ClassDescription { get { return classDescription; } } 

Sau đó, các lớp học của bạn được yêu cầu tuân theo hợp đồng có mô tả, nhưng bạn để nó cho họ để làm điều đó một cách hợp lý. Không có cách nào để chỉ định một triển khai thực hiện theo kiểu hướng đối tượng (ngoại trừ thông qua các hacks độc hại, dễ vỡ).

Tuy nhiên, trong tâm trí của tôi Mô tả này là siêu dữ liệu lớp, vì vậy tôi muốn sử dụng cơ chế thuộc tính như những người khác đã mô tả. Nếu bạn đặc biệt lo lắng về việc sử dụng nhiều phản chiếu, hãy tạo một đối tượng phản ánh thuộc tính mà bạn quan tâm và lưu trữ một từ điển giữa Loại và Mô tả. Điều đó sẽ giảm thiểu sự phản chiếu (ngoài kiểm tra kiểu thời gian chạy, mà không phải là tất cả những điều xấu). Từ điển có thể được lưu trữ như một thành viên của bất kỳ lớp nào thường cần thông tin này, hoặc, nếu các máy khách trên miền yêu cầu nó, thông qua một đối tượng đơn hoặc ngữ cảnh.

0

Bạn có thể đặt phương thức cơ sở "trừu tượng" ném Exception, do đó nhà phát triển sẽ "cảnh báo" nếu anh ta cố gắng gọi phương thức này trên lớp con mà không ghi đè.

Nhược điểm là người ta có thể mở rộng lớp và không sử dụng phương pháp này. Sau đó, tham khảo các câu trả lời khác được cung cấp.

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