2012-12-03 70 views
6

我已經查找了一些現在找到解決此問題的方法。我發現了幾種可以解決這個問題的方法,但說實話,我沒有意識到哪種方式可以被視爲「正確」的C#或OOP解決方式。我的目標不僅是要解決問題,而且要制定一套完善的代碼標準,並且我相當肯定有一個標準的方法可以解決這個問題。C#在一個列表中的不同類對象

比方說,我有兩種類型的打印機硬件及其各自的類和通信方式:PrinterType1,PrinterType2。

我還希望能夠稍後添加其他類型,如果需要的話。這些抽象概念有一個共同之處。作爲例子,應該可以向它們中的每一個發送一個字符串。它們都有共同的變量和每個類別獨有的變量。 (其中一個例如通過COM端口進行通信並且具有這樣的對象,而另一個通過TCP進行通信並且具有這樣的對象)。

但是,我想只是實現所有這些打印機的列表,並且能夠通過列表並執行所有打印機上的「發送(字符串消息)」,而不管類型如何。我還想訪問兩個對象相同的變量,例如「PrinterList [0] .Name」,但是我也會在某些地方訪問特定於對象本身的數據(例如,在設置窗口中COM端口名稱爲一個對象設置的應用程序以及另一個對象的IP /端口號)。

因此,簡而言之是這樣的:

共同點:

  • 名稱
  • 發送()

具體到PrinterType1:

  • 端口

具體到PrinterType2:

  • IP

而且我希望,例如,不要發送()上的所有對象,無論類型和現在的對象的數量。我已經閱讀了關於多態性,泛型,接口等的內容,但是我想知道在我眼中基本的這個問題通常會在C#(和/或一般的OOP)中處理。

我實際上已經嘗試做一個基類,但它對我來說並不完全正確。例如,我沒有在基類中使用「string Send(string Message)」函數。那麼爲什麼我會定義一個需要在派生類中重寫的地方,當我永遠不會在基類中使用函數時呢?

我非常感謝任何答案。這裏的人們看起來非常有知識,而且這個地方早就爲我提供了很多解決方案。現在我終於有一個帳戶來回答和投票了。

編輯:

額外解釋,我也想能夠訪問實際printertype的對象。例如PrinterType1中的Port變量,它是一個SerialPort對象。我想訪問它,如: PrinterList[0].Port.Open()

並有權訪問底層端口的全部功能。同時,我想調用相同的方式工作,針對不同的對象(但具有不同的實現)的通用功能:

foreach (printer in Printers) 
    printer.Send(message) 
+0

我建議,無論您選擇哪種解決方案,您都會選擇一本關於面向對象基礎知識的好書。一本好書也將提供示例,我相信您會看到WHEN和HOW如何使用您將選擇的各種語言功能。 –

+0

+1。希望開發一套好的代碼標準。 –

回答

9

a使用接口的僞示例。

public interface IPrinter 
{ 
    void Send(); 
    string Name { get; } 
} 

public class PrinterType1 : IPrinter 
{ 
    public void Send() { /* send logic here */ } 
    public string Name { get { return "PrinterType1"; } } 
} 

public class PrinterType2 : IPrinter 
{ 
    public void Send() { /* send logic here */ } 
    public string Name { get { return "Printertype2"; } } 

    public string IP { get { return "10.1.1.1"; } } 
} 


// ... 
// then to use it 
var printers = new List<IPrinter>(); 

printers.Add(new PrinterType1()); 
printers.Add(new PrinterType2()); 

foreach(var p in printers) 
{ 
    p.Send(); 

    var p2 = p as PrinterType2; 

    if(p2 != null) // it's a PrinterType2... cast succeeded 
    Console.WriteLine(p2.IP); 
} 
+0

感謝您提供非常好的建議。假設在PrinterType2中定義的IP變量是一個SerialPort Port對象,我想編輯它,我可以直接訪問它嗎? Port.Dispose(),Port.Name(),Port.Open()等。 –

+0

Interface僅公開所聲明的方法/屬性。如果您有一組IPrinter對象,則必須確定某個特定實例是否實際上是PrinterType2的一個實例,然後進行適當的轉換。 (這可以使用**是**和**作爲**運算符。) – ThatBlairGuy

+0

因此,如果一個類有一個Port對象,而另一個沒有,我用一個對象填充一個列表:PrinterType1和其中一個PrinterType2。其中只有一個具有「端口」對象。我怎樣才能訪問它?我很可能在這裏錯過了一些東西,但在上面的代碼中,我看不到如何訪問僅存在於兩個類中的一箇中的對象。你是否說我需要檢查列表成員的類型,將它轉換爲實際的類型(或者當我將它添加到列表中)並從那裏訪問和編輯實際的基礎對象? –

2

創建一個接口(比如IPrinterType)保存您的「共同」的方法和改用這個接口。

+0

謝謝你的回答。我已經調查了一些接口,但是從我讀過的內容你不能以這種方式使用變量。所以我必須把所有的變量都變成屬性,而不是我喜歡的。但它是一個解決方案。 –

0

你的描述幾乎是什麼接口設計的。將所有常見的屬性/方法放入其中,並隱藏具體的實現。我仍然建議有一個基地Printer類,因爲顯然會有類似的代碼可以共享。

當談到您提到的更多定義的屬性時,端口/ IP,你將不得不知道你在處理什麼類型。此時您可以將其轉換爲正確的類型。

+0

是的,它是那些我在某處擬合最麻煩的屬性。我想訪問只存在於其中一個派生類中的對象(例如SerialPort)。我想從基類訪問它,因爲列表是用該類型定義的。 –

+0

@jeah_wicer因此,您必須將其轉換爲特定的派生類型,例如'var castedObj = this作爲DerivedType; if(castedObj!= null){...}'。 – James

2

什麼你要找的是一個抽象基類,像這樣:

abstract class Printer 
{ 
    public string Name { get; set; } 
    public abstract string Send(string Message); 
} 

然後,從該類繼承並根據需要實現你的send()函數。

您也可以在這裏使用接口。區別在於一個接口只能指定繼承者必須實現的屬性,方法和事件 - 它本身並不實現任何代碼。你使用哪個取決於你的應用最適合什麼。你可能會結束這兩者(創建一個實現接口的抽象類)。

1

對於「我沒有在基類本身中使用」string Send(string Message)「函數的具體問題,那麼爲什麼我要定義一個需要在派生類中重寫的函數呢?首先我永遠不會在基類中使用函數?「

真的沒有必要在基類中實現它。

如果您的基類是一個抽象類,您可以簡單地聲明它,然後將其留給具體的類來實現它。

如果您不想提供任何具體的實現,那麼您可能會更好地使用所有具體類需要實現的接口。

相關問題