How to create a class that can instantiate another class and access private members of the owner

I'm not sure that what I want to do breaks the object-oriented recommendations or not, I will explain what I am doing, and I hope you guys can show me the best way if I am wrong. I tried asking this question before, but I gave a bad example, so I think it just caused more confusion.

So, I have a main class, USBCommunicator. The constructor accepts the product identifier of the type of device you want to talk to. The USBCommunicator class also has a property for a specific serial number for a conversation. USBCommunicator has the OpenConnection and CloseConnection methods that open or close the data stream for transferring data between the USB device and the PC.

To send data over the stream, I want USBCommunicator to be able to instantiate the Report class, set some parameters, such as timeouts, ReportID, etc., and then call the Send () method of the Report class to actually send the data. I do not think that any class other than USBCommunicator should be able to instantiate the Report class. (For example, a boat girl should not create instances of the CarDoor class because the boat cannot have a car door.) Finally, I initially thought that the Report class should have access to the members of the USBCommunicator, but I think it is not. If the USBCommunicator opens the stream, the device that really needs a report is the passed parameter, which is the open stream reference / descriptor. But what form should this stream be,so that it can be transferred by a high-level application? state property? This does not seem right.

So here is what I still have ...

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
source share
4 answers

Since it USBCommunicatormanages all important resources (including thread lifetime), applications should call USBCommunicator.Send, not Report.Send:

public class USBCommunicator {
    public void Send(Report report) {

        // If it appropriate, this method can also Open 
        // and Close the stream so callers don't have to.

        report.Send(this.stream);
    }
}

Then make it Report.Sendinternal so that it is not part of the open API, and applications can do this:

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);
}

I do not think that any class other than USBCommunicator should be able to instantiate the report class.

- , Report. , USBCommunicator :

// USBCommunicator
public void Send(int reportID, int timeout, string data) {
    Report report = new Report(reportID, timeout, data);
    report.Send(this.stream);
}
+3

, , Report.

, public, :

Report r = new Report();

USBCommunicator. - , , .

+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.
        }
    }
}

Your high-level application will look like this:

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();
    }        
} 
+1
source

Why don't you pass the whole class (either through a link or through copy)?

myUSB.Report ReportToSend = new myUSB.Report(ParentClassWithStream);

myUSB.Report must have a private element to store the link.


...
 class Report
        {
            ParentClassWithStream PC
            Report(ParentClassWithStream p)
            {
                PC = p

                //...
            }
            Send()
            {
                //send the data
            }
        }
...

0
source

Source: https://habr.com/ru/post/1733435/


All Articles