簡體   English   中英

我如何制作一個可以創建另一個類的實例並訪問所有者的私有成員的類

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM