我不确定我想要做什么会违反面向对象的指导方针,所以我会解释我在做什么,希望如果我错了,你们可以告诉我一个更好的方法。我之前尝试过问这个问题,但是我给出了一个很糟糕的例子,所以我认为这只会引起更多混乱。
所以我有一个主类,USBCommunicator。构造函数采用您要与之通信的设备类型的产品ID。 USBCommunicator类还具有要与之通信的特定序列号的属性。 USBCommunicator具有OpenConnection和CloseConnection方法,可以打开或关闭数据流,以便在USB设备和PC之间传输数据。
要在流中发送数据,我希望USBCommunicator能够创建一个Report类的实例,设置一些参数,如超时,ReportID等,然后调用Report类的Send()方法实际发送数据。我认为除USBCommunicator之外的任何类都不应该能够创建Report类的实例。 (例如,Boat lass不应该能够创建CarDoor类的实例,因为船不能有车门。)最后,我原本以为Report类应该能够访问USBCommunicator的成员但我想这不是真的。如果USBCommunicator打开设备的流,则所有报告确实需要的是传入的参数,即打开流的引用/句柄。但是,该流应该以什么形式允许它由高级应用程序传递?公共财产?这似乎不太正确。
所以这就是我到目前为止......
namespace USBTools
{
class HighLevelApplication
{
void main()
{
USBCommunicator myUSB = new USBCommunicator("15B3");
myUSB.SerialNumber = "123ABC";
myUSB.OpenConnection();
myUSB.Report ReportToSend = new myUSB.Report(//how do I pass the stream here?);
//It would be nice if I didn't have to pass in the stream because the stream shouldn't
//be publicly available to the HighLevelApplication class right?
ReportToSend.ReportID = 3;
ReportToSend.Timeout = 1000;
ReportToSend.Data = "Send this Data";
ReportToSend.Send();
}
}
class myUSB
{
myUSB(string PID)
{
//...
}
// public SerialNumber property
// private stream field ???
// public OpenConnection and CloseConnection methods
class Report
{
Report(stream StreamToUse)
{
//...
}
Send()
{
//send the data
}
}
}
}
答案 0 :(得分:3)
由于USBCommunicator
管理所有重要资源(包括流的生命周期),应用程序应调用USBCommunicator.Send
,而不是Report.Send
:
public class USBCommunicator {
public void Send(Report report) {
// If it's appropriate, this method can also Open
// and Close the stream so callers don't have to.
report.Send(this.stream);
}
}
接下来,将Report.Send
设为内部,使其不属于公共API,应用程序可以执行此操作:
public void main(string[] args) {
USBCommunicator myUSB = new USBCommunicator("15B3");
myUSB.SerialNumber = "123ABC";
myUSB.OpenConnection();
Report report = new Report(3, 1000, "Send this Data");
myUSB.Send(report);
}
我认为除了以外的任何课程 USBCommunicator应该能够 创建报告的实例 类。
您当前的设计并不能阻止这种情况 - 实际上,您的示例应用程序会创建Report
类的实例。如果你真的想要隐藏报告类,你应该将它设为私有USBCommunicator
并将其属性推送到通信器的界面,如下所示:
// USBCommunicator
public void Send(int reportID, int timeout, string data) {
Report report = new Report(reportID, timeout, data);
report.Send(this.stream);
}
答案 1 :(得分:1)
您没有显式访问私有成员,而是提供从Report类返回私有变量的公共属性。
只要您的报告类标记为public
,您就可以执行以下操作:
Report r = new Report();
在主USBCommunicator类中。但是永远不要将成员变量公开为public,它们应该在Report中是私有的,但是你应该包含公共属性来访问那些私有成员。
答案 2 :(得分:1)
以下会做你想要的。我们的想法是从实际实现中分离Report类的接口。这使您可以创建只有USBCommunicator对象才能创建的实现类。
public abstract class Report
{
protected Report() { }
public int ReportID {get; set;}
public int Timeout {get; set;}
public string Data {get; set; }
public abstract void Send();
}
public class USBCommunicator
{
private Stream m_stream;
public USBCommunicator (string PID)
{
//...
}
//Callers create new report objects via a method instead of directly using 'new'
public Report CreateReport()
{
return new ReportImpl(m_stream);
}
//Provides the implementation of the abstract methods of the Report class.
private class ReportImpl : Report
{
private Stream m_stream;
public ReportImpl(Stream stream)
{
m_stream = stream;
}
public void override Send()
{
//put implementation of Send here.
}
}
}
您的高级应用程序将变为:
class HighLevelApplication
{
void main()
{
USBCommunicator myUSB = new USBCommunicator("15B3");
myUSB.SerialNumber = "123ABC";
myUSB.OpenConnection();
Report reportToSend = myUSB.CreateReport();
reportToSend.ReportID = 3;
reportToSend.Timeout = 1000;
reportToSend.Data = "Send this Data";
reportToSend.Send();
}
}
答案 3 :(得分:0)
为什么不通过全班(通过引用或复制)?
myUSB.Report ReportToSend = new myUSB.Report(ParentClassWithStream);
myUSB.Report必须有一个私有成员来保存引用。
...
class Report
{
ParentClassWithStream PC
Report(ParentClassWithStream p)
{
PC = p
//...
}
Send()
{
//send the data
}
}
...