I am not sure if what I want to do breaks Object oriented guidelines or not so I will explain what I am doing and hopefully you guys can show me a better way if I am wrong. I tried asking this question before but I gave a poor example so I think it just caused more confusion.
So I have a main class, USBCommunicator. The constructor takes a Product ID of the type of device that you want to talk to. The USBCommunicator class also has a property for a specific serial number to talk to. USBCommunicator has OpenConnection and CloseConnection methods which will open or close a data stream to transfer data between the USB device and the PC.
To send data across the stream I want the USBCommunicator to be able to create an instance of a Report class, set some parameters such as timeouts, ReportID's etc, and then call a Send() method of the Report class to actually send the data. I don't think any class other than USBCommunicator should be able to create an instance of the Report class. (For example, a Boat lass shouldn't be able to create instances of CarDoor class because boat can't have a car door.) Finally, I was originally thinking that the Report class should be able to have access to the members of USBCommunicator but I guess that is not true. If USBCommunicator opens the stream the the device, all Report really needs is a parameter passed in that is a reference/handle to the open stream. But what form should that stream be that it would allow it to be passed by the high level application? a public property? That doesn't seem quite right.
So here is what I have so far...
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
}
}
}
}
Why don't you pass the whole class (either by ref or copy)?
myUSB.Report ReportToSend = new myUSB.Report(ParentClassWithStream);
myUSB.Report must have a private member to hold the reference.
The following would do what you want. The idea is to seperate the interface for the Report class from the actual implementation. That lets you create an implementation class that only your USBCommunicator object can create.
Your high level app then becomes:
Since
USBCommunicator
manages all the important resources (including the stream's lifetime), applications should callUSBCommunicator.Send
, notReport.Send
:Next, make
Report.Send
internal so it isn't part of the public API, and applications can do this:Your current design doesn't prevent this - indeed, your sample application is creates an instance of the
Report
class. If you really want to hide the report class, you should make it private toUSBCommunicator
and push its attributes out to the communicator's interface like this:You do not explicitly access private members, you provide public properties that return the private variables from your Report class.
Also as long as your report class is marked
public
, you can do:Within your main USBCommunicator class. But never expose member variables as public, they should be private within Report but you should include public properties to access those private members.