2013-04-18 30 views
14

Tôi đã đọc một số câu hỏi tương tự về vấn đề này nhưng không có câu hỏi nào giải quyết được vấn đề tôi đang gặp phải. Câu trả lời điển hình là để đúc như lớp dẫn xuất nhưng tôi không thể vì tôi không biết loại lớp dẫn xuất.Làm cách nào để gọi một phương thức lớp dẫn xuất từ ​​lớp cơ sở?

Dưới đây là ví dụ của tôi:

class WireLessDevice { // base class 
    void websocket.parsemessage(); // inserts data into the wireless device object 
} 

class WiFi : WireLessDevice { // derived class 
    GPSLoc Loc; 
} 

Device không dây cũng có thể được bắt nguồn để làm cho Bluetooth, Wi-Max, Cellular, vv các thiết bị và do đó tôi không biết đó là loại wirelessdevice sẽ nhận được các dữ liệu .

Khi nhận được gói GPS trên websocket trong lớp cơ sở, tôi cần cập nhật vị trí của thiết bị có nguồn gốc. Tôi nghĩ có lẽ việc gửi một tin nhắn thông qua hàng đợi hoặc tạo một trình xử lý sự kiện và gửi vị trí trong các đối số sự kiện, nhưng những điều đó có vẻ hơi khó khăn khi dữ liệu nằm trong lớp.

Có thứ gì đó được tích hợp sẵn trong ngôn ngữ cho phép tôi gọi thiết bị có nguồn gốc từ lớp cơ sở mà không biết loại đó không?

+0

Hãy xem mẫu trang trí. Vấn đề của bạn dường như là thiết kế sai lầm của bạn. –

+4

Không cần trang trí ... Hãy xem các phương pháp trừu tượng hoặc ảo ... – Crisfole

Trả lời

31

Cách chính xác là thêm phương thức DoSomeMagic() vào lớp cơ sở, với triển khai mặc định hoặc trừu tượng. Lớp dẫn xuất nên vượt qua nó để làm phép thuật của nó.

Something như thế này có lẽ:

public class WireLessDevice 
{ // base class 
    protected virtual void ParseMessage() 
    { 
     // Do common stuff in here 
    } 
} 

public class WiFi : WireLessDevice 
{ // derived class 
    override void ParseMessage() 
    { 
     base.ParseMessage();//Call this if you need some operations from base impl. 
     DoGPSStuff(); 
    } 
    private void DoGPSStuff() 
    { 
     //some gps stuff 
    } 
    GPSLoc Loc; 
} 
+4

+1 cho Magic ... – CSharpie

+0

Vì vậy, nếu tôi gọi this.setGPSLocation từ lớp cơ sở websocket.parsemessage() nó sẽ tự động gọi lớp bắt nguồn 'setGPSLocation? – CramerTV

+0

Tôi sẽ không gọi SetGPSLocation từ lớp cơ sở, nhưng trong lớp dẫn xuất. Sẽ cập nhật câu trả lời của tôi để chứng minh. –

2

Virtual methods sẽ là một giải pháp tốt. Bạn tạo một phương thức ParseMessage trong lớp cơ sở xử lý tất cả các công cụ phổ biến cho từng loại dẫn xuất, sau đó ghi đè cho các thiết bị cụ thể.

Để vẫn có thể xử lý các loại tin nhắn khác, bạn sẽ cần phải gọi base.ParseMessage như thích hợp:

class WireLessDevice 
{ 
    protected virtual bool ParseMessage(byte[] message) 
    { 
     // Inspect message and handle the known ones 
     return true; // Only if message parsed, otherwise false 
    } 
} 

class WiFi : WireLessDevice 
{ 
    GPSLoc Loc; 

    protected override bool ParseMessage(byte[] message)  
    { 
     bool messageParsed = base.ParseMessage(message) 
     if (!messageParsed) 
     { 
      // Handle device specific message with GPSLoc 
      Loc = ... 
     } 
     else 
     { 
      return false; 
     } 
    } 
} 

Nếu lớp cơ sở của bạn không xử lý bất kỳ tin nhắn khác, các mã có thể được đơn giản (và sử dụng abstract). Tuy nhiên, trong trường hợp đó, tôi sẽ xem xét việc chuyển mã ổ cắm web sang lớp dẫn xuất.

+1

Giải pháp này tương tự như của Omer và tôi tin rằng sẽ làm việc cho tôi. Tôi sẽ thử và cập nhật các câu trả lời. Cảm ơn Thorarin! – CramerTV

+0

@CramerTV Đó là những gì bạn nhận được để trả lời trong khi ai đó đang chỉnh sửa bài đăng của họ, nhưng vâng nó gần như giống hệt nhau. Tôi thích lời giải thích của tôi tốt hơn, vì vậy tôi giữ câu trả lời. – Thorarin

+0

Điều đó làm việc tuyệt vời Thorarin. Tôi đã sửa đổi giá trị trả về của bạn thành loại được liệt kê trong đó GPS là một trong các giá trị. Theo cách này, parseMessage thường trả về một giá trị cho biết loại tin nhắn nào đã được nhận và tôi chỉ cập nhật vị trí khi tin nhắn được phân tích tương ứng với tọa độ GPS (tôi có thể có các thông báo 'trường hợp đặc biệt' khác) .) Tôi cũng bao gồm một loại 'lỗi' trong liệt kê để tôi có thể nhận ra một sự thất bại như ví dụ của bạn ở trên. Cảm ơn câu trả lời của bạn. Tôi upvoted bạn cả hai nhưng chọn câu trả lời của Omer đơn giản chỉ vì ông là người đầu tiên. – CramerTV