2010-10-29 35 views
15

Giả sử bạn có hai lớp C# khác nhau AB trong khi không xuất phát từ cùng một lớp cơ sở thì hãy chia sẻ một số tên giống nhau cho các phương thức. Ví dụ: cả hai lớp đều có connect và phương thức disconnect cũng như một số lớp khác. Tôi muốn để có thể viết mã một lần mà sẽ làm việc với cả hai loại.Mã C# để xử lý các lớp khác nhau với cùng tên phương thức

Đây là một ví dụ đơn giản về những gì tôi muốn làm:

public void make_connection(Object x) 
{ 
    x.connect() ; 
    // Do some more stuff... 
    x.disconnect() ; 
    return ; 
} 

Tất nhiên, điều này không biên dịch như lớp Object không có một phương pháp connect hoặc disconnect.

Có cách nào để thực hiện việc này không?

CẬP NHẬT. Tôi nên làm điều này rõ ràng ngay từ đầu: Tôi chỉ có các DLL cho A và B chứ không phải nguồn.

+5

này là khá nhiều như thế nào tất cả mọi người học cách có giá trị các cấu trúc giao diện là. Bạn thực sự cần phải đánh một tình huống mà chúng hữu ích trước khi bạn "làm cho nó". –

Trả lời

26

Bạn có thể sử dụng một giao diện để thực hiện những gì bạn muốn làm.

interface IConnectable 
{ 
    void Connect(); 

    void Disconnect(); 
} 

Cả AB nên thực hiện IConnectable. Sau đó, sử dụng IConnectable thay vì Object làm loại thông số cho phương pháp của bạn và bạn nên được đặt.

public void MakeConnection(IConnectable connectable) 
{ 
    connectable.Connect(); 

    // Do some more stuff... 

    connectable.Disconnect(); 
} 

Edit: Vì bạn không có mã nguồn, bạn có một vài lựa chọn:

  1. giải pháp của việc sử dụng từ khóa dynamic, (nếu bạn đang sử dụng .NET Sử dụng Max 4,0)
  2. sử dụng của Steve giải pháp của việc sử dụng đúc và if/else báo cáo
  3. Tạo lớp wrapper cho AB và có họ thực hiện giao diện (hoặc sử dụng chung lớp cơ sở trừu tượng đối với họ)

Ví dụ:

class AWrapper : IConnectable 
{ 
    private A obj; 

    public AWrapper(A obj) 
    { 
     this.obj = obj; 
    } 

    public void Connect() 
    { 
     this.obj.Connect(); 
    } 

    public void Disconnect() 
    { 
     this.obj.Disconnect(); 
    } 

    // other methods as necessary 
} 

(BWrapper sẽ tương tự, chỉ cần sử dụng B thay vì A)

Sau đó, bạn có thể tạo trình bao bọc và chuyển chúng vào MakeConnection. Đó là vào bạn như thế nào bạn muốn làm điều đó. Tùy thuộc vào tình huống của bạn, một phương pháp có thể dễ dàng hơn những phương pháp khác.

+3

Là thực tế ở đây nhưng các lớp không * kế thừa * giao diện, chúng * thực hiện * chúng. – Phil

+0

@Phil: Cảm ơn! Đã sửa. –

+2

Làm thế nào để bạn thực hiện A và B thực hiện một giao diện nếu bạn không có mã nguồn đến A và B? – rlandster

2

Thử sử dụng Giao diện thay thế.

Có một cái nhìn tại interface (C# Reference)Interfaces (C# Programming Guide)

Vì vậy, một cái gì đó giống như

public interface IConnections 
{ 
    void connect(); 
    void disconnect(); 
} 

public class A : IConnections 
{ 
    public void connect() 
    { 
     //do something 
    } 

    public void disconnect() 
    { 
     //do something 
    } 
} 

public class B : IConnections 
{ 
    public void connect() 
    { 
     //do something 
    } 

    public void disconnect() 
    { 
     //do something 
    } 
} 

public void make_connection(IConnections x) 
{ 
    x.connect(); 
    // Do some more stuff... 
    x.disconnect(); 
    return; 
} 
1

Có một khái niệm OOAD của 'Programe để một giao diện không một thực hiện' mà cho phép của bạn tránh được những chuỗi thừa kế phân cấp

1- Bạn có thể tạo một interfcae

interface IConnection 
{ 
    void Connect(); 
    void Disconnect(); 
} 

2 - Và để cho các lớp của bạn thực hiện giao diện này như hình dưới đây.

class A : IConnection 
{ 
    #region IConnection Members 

    public void Connect() 
    { 
     // your connect method implementation goes here. 
    } 

    public void Disconnect() 
    { 
     // your disconnect method implementation goes here. 
    } 

    #endregion 
} 


class B : IConnection 
{ 
    #region IConnection Members 

    public void Connect() 
    { 
     // your connect method implementation goes here. 
    } 

    public void Disconnect() 
    { 
     // your disconnect method implementation goes here. 
    } 

    #endregion 
} 

3- Khi bạn thực hiện xong việc này, bạn có thể thực hiện chức năng chấp nhận đối số của IConnection như minh họa bên dưới.

public void makeConnection(IConnection con) 
    { 
     con.Connect(); 
     con.Disconnect(); 
    } 

4- Và từ mã khách hàng, bạn có thể chuyển đối tượng của lớp thực hiện Giao diện IConnect.

0

Hoặc bạn sẽ phải sử dụng một giao diện (hoặc lớp Base) như thể hiện bởi Zach và astander, hoặc bạn sẽ phải là trường hợp đối tượng trước khi sử dụng:

public void make_connection(Object x) 
{ 
    ((A)x).connect() ; 
    // Do some more stuff... 
    x.disconnect() ; 
    return ; 
} 
1

Nếu giải pháp giao diện là không thể (ví dụ bạn không có mã nguồn), một giải pháp ít hiệu quả hơn là sử dụng sự phản chiếu.

+0

+1 để có giải pháp bổ sung được sử dụng trong trường hợp không thể thực hiện được cách tiếp cận tiêu chuẩn (giao diện). – VitalyB

12

này sẽ làm việc trong C# 4:

public void make_connection(dynamic x) 
{ 
    x.connect() ; 
    // Do some more stuff... 
    x.disconnect() ; 
    return ; 
} 
+2

+1 để an toàn hơn, bạn có thể có các phương thức công khai được gõ mạnh - 'make_connection (A a)' - ủy nhiệm đó cho một phương thức động riêng. –

0

Bạn cũng có thể sử dụng phản ánh để gọi các phương pháp

1

Như những người khác đã nói, lại thanh toán để sử dụng giao diện hoặc sử dụng cách tiếp cận năng động có lẽ là cách thanh lịch nhất.

Nếu không thể, bạn có thể truyền đối tượng đến các loại của mình. Tôi khuyên bạn nên sử dụng as và sau đó kiểm tra xem dàn diễn viên có hoạt động hay không, một diễn viên không được chọn sẽ nguy hiểm nếu ai đó gọi tên này bằng loại không thể truyền.

Ví dụ: Nếu loại AB cả hai đều có một phương pháp gọi là DoSomething() thì điều này sẽ làm việc ...

public static void CallDoSomething(object o) 
    { 
     A aObject = o as A; 

     if (aObject != null) 
     { 
      aObject.DoSomething(); 
      return; 
     } 

     B bObject = o as B; 

     if (bObject != null) 
     { 
      bObject.DoSomething(); 
      return; 
     } 
    } 

NHƯNG này là khá xấu xí phải trung thực ... Tôi thực sự muốn thử và cấu trúc lại để giao diện.

0

Điều bạn muốn được gọi là Duck Typing.

Từ Wikipedia:

Duck gõ được một phong cách gõ năng động, trong đó thiết lập hiện tại của một đối tượng của phương pháp và tài sản xác định ngữ nghĩa có giá trị, chứ không phải là thừa kế từ một lớp học đặc biệt hoặc thi hành một giao diện cụ thể.

C# 4.0 cho phép này, vì khác đã nói, sử dụng động từ khóa

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