Short answers: Composition over inheritance . Program against interfaces . The principle of least privilege . Role-based interfaces .
I suggest you do Google on them after reading my post;)
First, you do not need to inherit InputStream from ViewController , as VieController.doSaveAsXML() is publicly available.
Even if he had private visibility | protected | package, we should not use inheritance only to access the method for another class that we do not see. Inheritance is intended to inherit, refine, or extend behavior, and not to access methods.
You can always pass the controller as an argument type to your input stream. If your input stream needs to access all the methods in the controller, pass the controller as is (or ask the controller to implement an interface with all its methods).
First of all, it is important to note that your InputStream does not need access to the controller. He only needs access to something that the file opening functions can do for him - he needs a file opener .
The second important thing to notice is that the controller (usually) does not need to know how to open files. The controller, as a rule, is the organizer or orchestra (due to the lack of a better word). Thus, it should not be a file opener (or independently implement the logic of opening a file). The controller just needs a link to aa file opener . Just like input stream , the controller just needs to delegate file opening logic to file opener .
In other words:
- your input stream must have access to the opening file
- your controller must also have access to the opening file
- your controller initializes your input stream, and so it must pass the file opener to it during initialization
- because of the foregoing, the controller itself must receive, create or configure the file opener itself.
- since the file opener is external to both the stream and the controller, the file opener must have an interface (which can be implemented using an xml file or any opener for that matter.)
java pseudocode:
public interface FileOpener { public void doOpen(); } public class XMLOpener implements FileOpener { public void doOpen(){ ... do xml specific file opening ... } } public interface Stream { public void init(FileOpener FileOpener); public void kickIt(); } public interface Controller {
If you go completely working with interface handlers, this is a design decision that we must implement with each project. But this approach (or something inspired by it), as a rule, is the way to go. It is much more difficult (but not impossible) to invent circular dependencies, and when they do occur, they are a configuration issue, not an internal problem with your object model.
Hope this helps.