StackOverflow 混乱

发布于 2024-10-15 22:03:36 字数 1415 浏览 5 评论 0原文

我是一个java新手,并且在StackOverflow错误/在类之间访问文件的能力方面遇到了一个非常令人困惑的问题。我知道根本原因可能是我进行了一些递归调用,但修复它的语法却让我无法理解。我认为这与类如何通过扩展另一个类进行链接有关 - 但是,如果 InputScreen 类不扩展 ViewController,我将无法访问我需要的方法。我已将高级代码放在下面(制作一个程序来跟踪汽油里程)。

这样做的目标是能够打开包含一些历史里程数据的 xml 文件(使用 doOpenAsXML() 方法),然后允许用户将数据添加到某些文本字段(在 InputScreen 类中定义),添加另一个数据点ArrayList,然后使用 doSaveAsXML 方法保存。

有人对如何使这项工作有想法吗?谢谢!!!


// 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
}

公共类 ViewController 扩展 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 hist 的语句,在 ViewController 方法中打开 doSaveAsXML(); }

I'm a java newbie, and am having a very confusing issue with StackOverflow errors / ability to access files between classes. I understand that the underlying cause is likely that I have some recursive call, but the syntax of fixing it is escaping me. I think it has something to do with how the classes are linked through one extending another -- but, if the InputScreen class doesn't extend the ViewController, I can't access the methods there that I need. I've put the high-level code below (making a program to track gas mileage).

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

Anyone have 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
    }

}

public class InputScreen extends ViewController {
// 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
doSaveAsXML();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

债姬 2024-10-22 22:03:36

这似乎是您问题的根本原因:

但是,如果 InputScreen 类没有扩展 ViewController,我将无法访问我需要的方法。

要访问另一个类中的(非静态)方法,您需要此类的对象。在您的情况下,InputStream需要拥有一个ViewController对象,而不是成为一个ViewController对象。 (同样,ViewController 不应该 JFrame,而是一个 - 尽管这不会产生问题。)

如果您更改此设置,则不会获取你的构造函数循环。

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

This seems to be the root cause of your problem:

but, if the InputScreen class doesn't extend the ViewController, I can't access the methods there that I need.

To access (non-static) methods in another class, you need an object of this class. In your case, the InputStream would need to have a ViewController object, not to be a ViewController object. (On the same lines, the ViewController should not be a JFrame, but have one - although this does not give problems here.)

If you change this, you don't 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();
    }
}
氛圍 2024-10-22 22:03:36

你是说InputScreen扩展了ViewController吗?这看起来像是构造函数中的无限递归循环。而且,

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

什么也不做。您创建一个新的InputScreen,将其设置为变量home,一旦构造函数完成,它就会立即被GCed。

Are you saying that InputScreen extends ViewController? That seems like it would be an infinite recursive loop right there in the constructor. Also,

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

doesn't do anything. You create a new InputScreen set it to the variable home, which promptly gets GCed as soon as the constructor finishes.

鹿童谣 2024-10-22 22:03:36

简短回答:组合优于继承针对接口进行编程最小权限原则角色接口

我建议您在阅读我的文章后对它们进行谷歌搜索;)

一方面,您不需要 InputStreamViewController 继承为 VieController.doSaveAsXML () 是公开的。

即使它具有 private|protected|package 可见性,我们也不应该仅使用继承来访问我们不可见的其他类上的方法。继承用于继承细化扩展行为,而不是用于访问方法。

您始终可以将控制器作为参数类型传递给输入流。如果您的输入流需要访问控制器中的所有方法,请按原样传递控制器(或者让控制器实现一个包含其中所有方法的接口。)

首先要注意的重要事情是您的 < code>InputStream 并不真正需要访问控制器。它只需要访问可以执行文件打开功能的东西 - 它需要一个文件打开器

需要注意的第二件重要事情是控制器(通常)也不需要知道如何打开文件。控制器通常是组织者或编排者(因为缺乏更好的词。)因此,它不需要是文件打开器(或实现文件打开逻辑本身。)控制器只需要对 aa 的引用文件打开器。就像输入流一样,控制器只需将文件打开逻辑委托给文件打开器即可。

换句话说:

  1. 你的输入流需要有
    访问文件打开器
  2. 您的控制器也只需要
    可以访问文件打开器
  3. 您的控制器初始化您的
    输入流,因此,它需要
    在期间将文件打开器传递给它
    初始化
  4. 由于上述原因,控制器
    本身需要接收,
    实例化或配置为
    文件打开器本身。
  5. 因为文件打开器位于外部
    流和控制器,
    文件打开器应该是
    接口(可以实现
    通过 xml 文件打开器或任何打开器
    无论

java 伪代码:

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

您是否一直让一切都针对接口处理程序工作,这是我们必须对每个项目做出的设计决策。但这种方法(或受其启发的方法)通常是可行的方法。通过这种方式(但并非不可能)提出循环依赖关系要困难得多,并且当它们确实发生时,它们是配置问题,而不是对象模型的内在问题。

希望有帮助。

Short answers: Composition over inheritance. Program against interfaces. Principle of Least Privilege. Role interfaces.

I'd suggest you do a google on them after reading my post ;)

For one thing, you do not need InputStream to inherit from ViewController as VieController.doSaveAsXML() is public.

Even if it had private|protected|package visibility, we should not use inheritance only to access a method on some other class that is not visible to us. Inheritance is for inheriting, refining or extending behavior, not for accessing methods.

You can always pass the controller as an argument type to your input stream. If your input stream needs to access all methods in the controller, pass the controller as is (or have the controller implement an interface with all the methods in it.)

First important thing to notice is that your InputStream doesn't really need access to a controller. It only need access to something that can do file opening functions for it - it needs a file opener.

Second important thing to notice is that the controller (typically) doesn't need to know how to open files either. A controller is typically an organizer or orchestrator (for lack of a better word.) As such, it doesn't need to be a file opener (or implement file opening logic itself.) The controller just needs a reference to a a file opener. Just like the input stream, the controller needs to simply delegate file opening logic to a file opener.

In other words:

  1. your input stream needs to have
    access to a file opener
  2. your controller also only needs to
    have access to a file opener
  3. your controller initializes your
    input stream, and so, it needs to
    pass a file opener to it during
    initialization
  4. because of the above, the controller
    itself needs to receive,
    instantiates or be configured with a
    file opener itself.
  5. since the file opener is external to
    both the stream and the controller,
    the file opener should be an
    interface (which can be implemented
    by a xml file opener 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() );

Whether you go all the way making everything working against interface handlers, that's a design decision that we have to make with every project. But this approach (or something inspired by it) is typically the way to go. It is much harder this way (but not impossible) to come up with cyclical dependencies, and when they do occur, they are a matter of configuration, and not of an intrinsic problem with you object model.

Hope it helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文