[英]How do I make a class that can create an instance of another class and access private members of the owner
我不確定我想做的事情是否違反了面向對象的准則,因此我將解釋我在做什么,並希望你們能給我一個更好的方法,如果我錯了。 我曾嘗試問過這個問題,但我舉了一個不好的例子,所以我認為這引起了更多的混亂。
所以我有一個主要的課程,USBCommunicator。 構造函數采用您要與之交談的設備類型的產品ID。 USBCommunicator類還具有與特定序列號進行通信的屬性。 USBCommunicator具有OpenConnection和CloseConnection方法,它們將打開或關閉數據流以在USB設備和PC之間傳輸數據。
為了跨流發送數據,我希望USBCommunicator能夠創建Report類的實例,設置一些參數(例如超時,ReportID等),然后調用Report類的Send()方法來實際發送數據。 我認為除USBCommunicator之外的任何其他類都不能創建Report類的實例。 (例如,Boat lass不能創建CarDoor類的實例,因為Boat不能有車門。)最后,我本來以為Report類應該能夠訪問USBCommunicator的成員。但我想那是不對的。 如果USBCommunicator打開設備上的流,則Report真正需要的只是一個傳入的參數,該參數是打開流的引用/句柄。 但是,該流應以什么形式允許高層應用程序傳遞? 公共財產? 這似乎不太正確。
所以這就是我到目前為止所擁有的...
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
}
}
}
}
由於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類的實例。
您當前的設計並不能防止這種情況-實際上,您的示例應用程序正在創建Report
類的實例。 如果您確實想隱藏報告類,則應將其設為USBCommunicator
私有的,並將其屬性推送到通信器的界面,如下所示:
// USBCommunicator
public void Send(int reportID, int timeout, string data) {
Report report = new Report(reportID, timeout, data);
report.Send(this.stream);
}
您沒有顯式訪問私有成員,而是提供了從Report類返回私有變量的公共屬性。
同樣,只要您的報告類別標記為public
,您就可以執行以下操作:
Report r = new Report();
在您的主要USBCommunicator類中。 但是永遠不要將成員變量公開,它們應該在Report中是私有的,但是您應該包括公共屬性以訪問那些私有成員。
以下將滿足您的要求。 想法是將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();
}
}
您為什么不通過(通過引用或復制)整個課程?
myUSB.Report ReportToSend = new myUSB.Report(ParentClassWithStream);
myUSB.Report必須具有私有成員才能保存引用。
...
class Report
{
ParentClassWithStream PC
Report(ParentClassWithStream p)
{
PC = p
//...
}
Send()
{
//send the data
}
}
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.