2009-03-02 58 views
11

Trong C#, tôi có lớp cơ sở Sản phẩm và lớp dẫn xuất Widget.C#: Làm thế nào để gọi một phương thức tĩnh của một lớp cơ sở từ một phương thức tĩnh của một lớp dẫn xuất?

Sản phẩm chứa phương pháp tĩnh MyMethod().

Tôi muốn gọi phương thức tĩnh Product.MyMethod() từ phương thức tĩnh Widget.MyMethod().

Tôi không thể sử dụng từ khóa cơ sở, vì từ khóa đó chỉ hoạt động với các phương pháp mẫu.

Tôi có thể gọi Product.MyMethod() một cách rõ ràng, nhưng nếu sau này tôi thay đổi Widget để lấy được từ một lớp khác, tôi phải sửa lại phương thức.

Có một số cú pháp trong C# tương tự như cơ sở cho phép tôi gọi một phương thức tĩnh từ một lớp cơ sở từ một phương thức tĩnh của một lớp dẫn xuất không?

+1

Bất kỳ lý do gì khiến phương pháp cụ thể này là tĩnh? – Rad

Trả lời

16

static phương pháp cơ bản là một phương pháp để dự phòng từ các khái niệm hướng đối tượng. Kết quả là, chúng không phải là rất linh hoạt trong các hệ thống phân cấp thừa kế và nó không thể làm một điều như vậy trực tiếp.

Điều gần nhất tôi có thể nghĩ là chỉ thị using.

using mybaseclass = Namespace.BaseClass; 

class MyClass : mybaseclass { 

    static void MyMethod() { mybaseclass.BaseStaticMethod(); } 

} 
+4

> phương pháp tĩnh về cơ bản là phương thức dự phòng ... Tại sao điều này đúng? Trong mã cho lớp của tôi, các phương thức dựa vào dữ liệu cá thể là các phương thức mẫu. Các phương thức không dựa vào dữ liệu cá thể, nhưng chỉ dựa vào các tham số (nếu có) là các phương thức tĩnh. Tôi thấy sự khác biệt này hữu ích. – MindModel

+0

Một phương thức không dựa vào một cá thể * đối tượng * không chơi bởi hầu hết các quy tắc được xác định cho các đối tượng (phương thức gửi đi ảo, ...). –

+0

mindmodel, trong khi có một số kịch bản cho nó, nếu bạn bắt đầu cần thừa kế hoặc [chèn bất kỳ hạn chế khác so với phương pháp không tĩnh] nó là một triệu chứng mà cái gì khác có thể được tắt ... có lẽ lớp có quá nhiều trách nhiệm – eglasius

0

Có vào tài khoản đó một phương pháp tĩnh shoudn't tiếp trong dữ liệu ví dụ ... bạn nên có một "MyMethod" tĩnh mà ứng xử khác nhau dựa trên một tham số hoặc một cái gì đó như thế. Hãy nhớ rằng phương pháp tĩnh được định nghĩa trong một lớp chỉ là một cách để đặt hàng mã của bạn ... nhưng nó là như nhau nếu phương pháp đó được đặt ở nơi khác ... bởi vì nó không chuyển tiếp trên đối tượng mà nó được đặt ở đâu đó. được đặt.

EDIT: Tôi nghĩ rằng lựa chọn tốt nhất của bạn là sử dụng Product.MyMethod một cách rõ ràng ... Nếu bạn nghĩ ... không nên có khả năng Widget của bạn thay đổi cơ sở của nó ... và cũng có thể trường hợp nó là một sự thay đổi nhỏ trong mã.

+0

Không hoàn toàn đúng. các phương thức tĩnh có thể dựa vào các thành viên private của một kiểu (cả static và instance), kết quả là chúng không hoàn toàn có thể di chuyển được. –

+0

Đúng. Bạn biết sự khác nhau giữa các biến tĩnh (một biến cho mỗi lớp) và các biến mẫu (một biến cho mỗi thể hiện). Tại sao sự khác biệt này không hữu ích? Tại sao nó là thiết kế OO xấu? – MindModel

+0

Vâng, tôi nên nói rằng bạn "Không nên" không chuyển tiếp trong dữ liệu biến dụ ... tất nhiên bạn "CÓ THỂ". :) – Romias

1

Phương pháp tĩnh không đa hình, vì vậy những gì bạn muốn làm là không thể.

Cố gắng tìm cách điều trị các phương pháp tĩnh như đa hình là có thể nhưng nguy hiểm, bởi vì chính ngôn ngữ không hỗ trợ nó.

Một số gợi ý:

4

Nó có thể được thực hiện, nhưng tôi không khuyên bạn nên nó.

public class Parent1 
{ 
    public static void Foo() 
    { 
     Console.WriteLine("Parent1"); 
    } 
} 

public class Child : Parent1 
{ 
    public new static void Foo() 
    { 
     Type parent = typeof(Child).BaseType; 
     MethodInfo[] methods = parent.GetMethods(); 
     MethodInfo foo = methods.First(m => m.Name == "Foo"); 
     foo.Invoke(null, null); 
    } 
} 
+4

Đủ công bằng. Trong trường hợp này, giải pháp là tồi tệ hơn vấn đề. Cảm ơn. – MindModel

+0

Chính xác. 10 ký tự – marcumka

+2

nstead sử dụng chuỗi bạn có thể sử dụng MethodBase.GetCurrentMethod() Tên –

0

Phương pháp tĩnh là phương pháp "Cấp độ". Chúng được dự định là các phương thức áp dụng cho tất cả các cá thể của một lớp cụ thể. Do đó, kế thừa của phương thức này không có ý nghĩa vì nó sẽ thay đổi ý nghĩa để áp dụng cho các cá thể của lớp. Ví dụ, nếu bạn đang lặp qua một tập hợp các Sản phẩm (một số Widget, một số không) và được gọi là MyMethod trên mỗi Sản phẩm thì phương thức được gọi sẽ được xác định bởi cá thể của lớp. Điều này vi phạm mục đích của các phương pháp tĩnh.Bạn có thể có thể làm một cái gì đó như bạn muốn sạch hơn bằng cách đơn giản là không sử dụng phương pháp tĩnh ở tất cả, bởi vì trong ví dụ của bạn nó không có vẻ như MyMethod áp dụng cho tất cả các trường hợp của sản phẩm. Tuy nhiên, bạn có thể đạt được ảnh hưởng tương tự như bạn đang mô tả bằng cách sử dụng một lớp giao diện như ‘IMyMethod’. Cách tiếp cận này vẫn không sử dụng phương pháp tĩnh. Tôi đoán tôi không thấy cần một phương pháp tĩnh. Tại sao bạn muốn sử dụng một phương thức tĩnh để bắt đầu?

4

Gọi một phương thức tĩnh bằng cách sử dụng sự phản chiếu giống hệt như gọi một phương thức thể hiện ngoại trừ việc bạn truyền null cho cá thể. Bạn cần FlattenHierarchy vì nó được định nghĩa trong một tổ tiên.

var type = assy.GetType("MyNamespace.MyType"); 
MethodInfo mi = type.GetMethod("MyStaticMethod", 
    BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy); 
mi.Invoke(null, null); 

Đọc thêm và suy nghĩ để lại cho tôi những câu hỏi tương tự như những người khác đã trả lời: tại sao lại sử dụng các phương pháp tĩnh như thế này? Bạn đang cố gắng để làm lập trình chức năng, và nếu vậy tại sao không sử dụng biểu thức lambda thay thế? Nếu bạn muốn các hành vi polymophic với trạng thái chia sẻ, các phương thức thể hiện sẽ tốt hơn.

-1

Rất đơn giản. Đơn giản hơn nhiều so với việc sử dụng bí danh, phản xạ, v.v. Có lẽ nó được thực hiện dễ dàng hơn trong các bổ sung mới hơn của .NET, IDK, nhưng nó hoạt động hoàn toàn tốt. Cũng giống như với các phương thức ví dụ, việc truy cập các phương thức cơ bản không yêu cầu base được sử dụng, nó là tùy chọn, thường là cần thiết khi lớp kế thừa và cơ sở có một phương thức có cùng tên. Ngay cả khi không có từ khóa base, bạn có thể truy cập các phương thức tĩnh của một lớp cơ sở như thể chúng nằm trong lớp bạn đang gọi. Tôi chỉ thử nghiệm điều này khi gọi phương thức tĩnh tĩnh từ phương thức tĩnh của phương thức bắt buộc. Có thể không hoạt động nếu bạn đang gọi từ phương thức dụ đến phương thức tĩnh.

public class BaseThings 
{ 
    protected static void AssertPermissions() 
    { 
     //something 
    } 
} 

public class Person:BaseThings 
{ 
    public static void ValidatePerson(Person person) 
    { 
     //just call the base static method as if it were in this class. 
     AssertPermissions();    
    } 
} 
+0

Aaron, OP có cùng tên phương thức cho các lớp cơ sở và có nguồn gốc. Cùng với thực tế là cô ấy không muốn chỉ định 'Base.StaticMethod' một cách rõ ràng, hai điều này là mấu chốt của vấn đề. – nawfal

2

Trước hết, nếu bạn lo lắng về việc sắp xếp lại lớp học, có thể bạn đang làm sai kế thừa. Thừa kế nên được sử dụng để thiết lập các mối quan hệ "là-a", không chỉ đơn giản là sử dụng lại mã nuôi dưỡng. Nếu bạn cần sử dụng lại mã một mình, hãy xem xét sử dụng ủy quyền, chứ không phải là thừa kế. Tôi cho rằng bạn có thể giới thiệu một loại trung gian giữa một loại phụ và cha mẹ của nó, nhưng tôi sẽ để cho rằng khả năng lái xe thiết kế của tôi. Thứ hai, nếu bạn cần sử dụng chức năng từ lớp cơ sở nhưng mở rộng nó và trường hợp sử dụng gọi một phương thức tĩnh, thì bạn có thể muốn xem xét sử dụng một số lớp bên ngoài để giữ chức năng. Trường hợp cổ điển cho điều này trong tâm trí của tôi là mẫu Nhà máy. Một cách để thực hiện mô hình Nhà máy là thông qua các Phương thức Nhà máy, một phương thức tĩnh trên một lớp để tạo ra một cá thể của lớp đó. Thông thường, hàm tạo được bảo vệ sao cho phương thức factory là cách duy nhất để xây dựng class từ bên ngoài. Một cách để tiếp cận tái sử dụng với Phương thức Nhà máy trong một hệ thống phân cấp thừa kế là đặt mã chung vào một phương thức được bảo vệ và gọi phương thức đó từ Phương thức Factory thay vì gọi trực tiếp lớp cơ sở Phương thức Nhà máy từ một phân đoạn phụ các loại phương pháp nhà máy. Việc triển khai tốt hơn có thể sử dụng cùng một kỹ thuật nhưng di chuyển phương thức Factory sang lớp Factory và sử dụng logic của hàm dựng (nội bộ bây giờ, không riêng tư), có lẽ kết hợp với (các) phương thức khởi tạo, để tạo đối tượng. Nếu hành vi bạn đang thừa kế là bên ngoài lớp (giải mã/xác nhận/etc), bạn có thể sử dụng các phương thức chia sẻ (hoặc thành phần) trong Nhà máy để cho phép tái sử dụng giữa các phương thức Factory.

Nếu không biết mục tiêu sử dụng các phương pháp tĩnh của bạn, thật khó để cung cấp cho bạn hướng chính xác, nhưng hy vọng điều này sẽ hữu ích.

2

Nó có thể được thực hiện:

public class Parent1 
{ 
    protected static void Foo() 
    { 
     Console.WriteLine("Parent1"); 
    } 
} 

public class Child : Parent1 
{ 
    public static void Foo() 
    { 
     return Parent1.Foo(); 
    } 
} 

có thể có ích cho kiểm tra đơn vị phương pháp tĩnh được bảo vệ (ví dụ).

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