7

我现在环顾四周以找到解决此问题的方法。我找到了几种可以解决它的方法,但老实说,我没有意识到哪些方法会被认为是“正确的”C# 或 OOP 解决方法。我的目标不仅是解决问题,而且是开发一套好的代码标准,我相当确定有一个标准的方法来处理这个问题。

假设我有 2 种类型的打印机硬件,它们各自的类和通信方式:PrinterType1、PrinterType2。

如果需要,我还希望以后能够添加另一种类型。抽象的一步,它们有很多共同点。作为示例,应该可以向它们中的每一个发送一个字符串。它们都有共同的变量和每个类独有的变量。(例如,一个通过 COM 端口进行通信并具有这样的对象,而另一个通过 TCP 进行通信并具有这样的对象)。

但是,我只想实现所有这些打印机的列表,并能够通过列表并在所有打印机上执行“发送(字符串消息)”,无论类型如何。我还想访问两个对象都相同的变量,例如“PrinterList[0].Name”,但是我也想在某些地方访问特定于对象本身的数据(例如在为一个对象设置 COM 端口名称而为另一个对象设置 IP/端口号的应用程序)。

所以,简而言之,就像:

共同点:

  • 姓名
  • 发送()

特定于 PrinterType1:

  • 港口

特定于 PrinterType2:

  • 知识产权

例如,我希望对所有对象执行 Send(),而不管对象的类型和存在的数量。

我已经阅读了有关多态性、泛型、接口等的内容,但我想知道在我看来基本的问题通常如何在 C#(和/或一般的 OOP)中处理。

实际上,我确实尝试过创建一个基类,但对我来说似乎不太合适。例如,我在基类本身中没有使用“字符串发送(字符串消息)”函数。那么,当我从一开始就永远不会使用基类中的函数时,为什么我要在那里定义一个需要在派生类中重写的函数呢?

我真的很感谢任何答案。这里的人似乎知识渊博,这个地方早些时候为我提供了许多解决方案。现在我终于有一个帐户可以回答和投票了。

编辑:

另外解释一下,我还希望能够访问实际打印机类型的对象。例如 PrinterType1 中的 Port 变量,它是一个 SerialPort 对象。我想像这样访问它: PrinterList[0].Port.Open()

并可以访问底层端口的全部功能。同时,我想调用对不同对象以相同方式工作的通用函数(但具有不同的实现):

foreach (printer in Printers)
    printer.Send(message)
4

5 回答 5

10

使用接口的伪示例。

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);
}
于 2012-12-03T16:19:34.637 回答
2

创建一个IPrinterType包含“常用”方法的接口(例如)并改用此接口。

于 2012-12-03T16:18:36.050 回答
2

您正在寻找的是一个抽象基类,如下所示:

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

然后,您从该类继承并根据需要实现您的 Send() 函数。

您也可以在此处使用接口。不同之处在于接口只能指定继承者必须实现的属性、方法和事件——它本身不实现任何代码。您使用哪种取决于最适合您的应用程序。您很可能会同时做这两件事(创建一个实现接口的抽象类)。

于 2012-12-03T16:19:54.300 回答
1

对于“例如,我在基类本身中没有使用“字符串发送(字符串消息)”函数的具体问题。那么,当我永远不会使用时,为什么我要在那里定义一个需要在派生类中覆盖的函数基类中的函数首先是什么?”

实际上没有必要在基类中实现它。

如果您的基类是抽象类,您可以简单地声明它,然后将其留给具体类来实现。

如果您不想提供任何具体的实现,那么您最好使用一个所有具体类都必须实现的接口来代替抽象类。

于 2012-12-03T16:21:55.857 回答
0

您的描述几乎就是设计的接口。将所有通用属性/方法放入其中并隐藏具体实现。我仍然建议使用基Printer类,因为显然会有类似的代码可以共享。

当涉及到您提到的更多定义的属性时,例如端口/IP,您必须知道您正在处理什么类型。此时,您可以将其转换为正确的类型。

于 2012-12-03T16:19:43.153 回答