Confusion Stackoverflow

I am new to java and I have a very confusing issue with StackOverflow errors / ability to access files between classes. I understand that the main reason is probably because I have some kind of recursive call, but the syntax for fixing it eludes me. I think this has something to do with how the classes are related to each other, but if the InputScreen class does not extend the ViewController, I cannot access those where I need to. I set the high-level code below (so that the program tracks the gas mileage).

The goal is to open an xml file with some historical mileage data (using the doOpenAsXML () method), and then allow the user to add data to some text fields (defined in the InputScreen class), add another data point to an ArrayList, and then save with using the doSaveAsXML method.

Anyone have any ideas on how to make this work? Thanks!!!

// Simple main just opens a ViewController window public class MpgTracking { public static void main(String[] args) { ViewController cl = new ViewController(); cl.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cl.setVisible(true); } // end main } 

public class ViewController extends JFrame {

  // the array list that I want to fill using the historical data public ArrayList<MpgRecord> hist; public ViewController() { doOpenAsXML(); // open historical data, put into 'hist' InputScreen home = new InputScreen (); } public void doSaveAsXML() { // ...long block to save in correct xml format } public void doOpenAsXML() { // ...long block to open in correct xml format } 

}

InputScreen ViewController { // "" // "" // ArrayList, ViewController doSaveAsXML(); }

code>
0
java stack-overflow
source share
3 answers

This seems to be the main cause of your problem:

but if the InputScreen class does not extend the ViewController, I cannot access those where I need to.

To access (non-static) methods in another class, you need an object of this class. In your case, the InputStream should have a ViewController, and not be a ViewController. (The ViewController should not have a JFrame in the same lines, but it has one, although there are no problems here).

If you change this, you will not get your constructor loop.

 public class ViewController { ... public ViewController() { doOpenAsXML(); // open historical data, put into 'hist' InputScreen home = new InputScreen (this); // give myself to our new InputScreen. // do something with home } public void doSaveAsXML() { // ...long block to save in correct xml format } public void doOpenAsXML() { // ...long block to open in correct xml format } } public class InputScreen { private ViewController controller; public InputScreen(ViewController contr) { this.controller = contr; } void someMethod() { // statements to define a screen with text fields and a 'Save' button // statements to create a listener on the Save button // statements to add to the ArrayList hist, opened in the ViewController method controller.doSaveAsXML(); } } 
+1
source share

Are you saying InputScreen extends ViewController? It seems to be an infinite recursive loop right in the constructor. Besides,

 public ViewController() { doOpenAsXML(); // open historical data, put into 'hist' InputScreen home = new InputScreen (); } 

doing nothing. You create a new InputScreen that sets it to the home variable, which quickly gets GCed as soon as the constructor finishes.

+1
source share

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 { /** inits stream with controller **/ public void init(FileOpener FileOpener); public void kickIt(); } public interface Controller { // defines other methods implemented by actual interfaces. public void kickIt(); } public class ViewController implements Controller { private Stream stream; private FileOpener opener; public ViewController( final Stream stream. final FileOpener opener ) { this.stream = stream; this.opener = opener; this.stream.init(this.opener); } public void kickIt(){ stream.kickIt() ); } public class InputStream implements Stream { private FileOpener opener; public InputStream() { } public Stream init(final FileOpener opener ) { this.opener = opener; } public void kickIt() { this.opener.doOpen(); } } .... Controller controller = new ViewController( new InputStream(), new XMLOpener() ); 

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.

0
source share

All Articles