Java抽象类混淆:未被调用的重写方法

时间:2009-03-15 00:32:09

标签: java abstract-class

所以我有两节课。一个是抽象的:

public abstract class AbstractClient {
    protected boolean running = true;

    protected void run() {
        Scanner scanner = new Scanner(System.in);
        displayOptions();
        while (running) {
            String input = null;
            while (scanner.hasNext()) {
                input = scanner.next();
            }
            processInputCommand(input);
        }
    }

    abstract void displayOptions();

    abstract void processInputCommand(String input);

}

一个是具体的子类:

public class BasicClient extends AbstractClient {
    private IBasicServer basicServer;

    public static void main(String[] args) {
        new BasicClient();
    }

    public BasicClient() {
        try {
            System.setSecurityManager(new RMISecurityManager());
            Registry registry = LocateRegistry.getRegistry();
            basicServer =  (IBasicServer) registry.lookup(IBasicServer.LOOKUPNAME);
            run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    void displayOptions() {
        BasicClientOptions.displayOptions();

    }

    @Override
    void processInputCommand(String input) {
        // TODO Auto-generated method stub

    }
}

现在在子类中,我调用抽象类的run()方法,因为这应该对所有客户端都是通用的。 run()方法内部是对抽象方法displayOptions()的调用。

我已经在子类中重写了displayOptions(),所以我假设它会调用子类方法,但它似乎没有。有没有办法做到这一点,或者我犯了一个明显的错误,或者我误解了抽象类应该如何工作?

P.S我尝试在子类化的displayOptions()中放置一个print语句,以确保我没有用我调用的方法做些蠢事。

非常感谢,

亚当

4 个答案:

答案 0 :(得分:4)

您的BasicClientOptions.displayOptions()电话可能出现问题。我想知道你怎么知道BasicClient.displayOptions()没有被召唤。

这是您所拥有的简化版本。尝试运行它。它表现得像你期望的那样。

public abstract class BaseClass {
    public void run() { foo(); }
    public abstract void foo();
}

public class Subclass extends BaseClass {

    public static void main(String[] args) { new Subclass().run(); }

    @Override
    public void foo() {
        System.out.println("I'm from the subclass");
    }
}

答案 1 :(得分:2)

类是否在不同的包中?如果是这样,您需要将方法声明为覆盖为受保护。

编辑:(猜一个解释可能会有所帮助: - )

如果您声明一个方法public / protected,那么它可以被包外的子节点覆盖。如果你做(包)/私人,那么它不能。私有方法根​​本不能被覆盖,(package)只能被同一个包中的类覆盖。

我使用(包)因为它没有关键字,所以在没有public / protected / private的情况下,你得到(包)访问。

编辑:

根据您的描述,上述情况可能不正确(假设该类确实是抽象的,并且您已使用@Override注释)。

您是否100%确定调用run方法?将System.out.println置于运行状态并确保调用它。

您是否100%确定您没有捕获任何其他异常并且无法打印出堆栈跟踪(或其他可确保您发现异常被捕获的内容)?

答案 2 :(得分:0)

不确定问题是什么,可以打印一些输出(带有打印语句)。

我复制/粘贴你的代码,除了评论一两行,我没有对象的正确来源。它为我调用了子类方法。

从逻辑上讲,阅读你的代码似乎不合适,但我更愿意亲眼看到一些东西,以确保没有其他问题,所以我尝试先运行你的代码。 :)

这是我修改的内容和输出。

import java.util.Scanner;

public abstract class AbstractClient {
  protected boolean running = true;

  protected void run() {
    Scanner scanner = new Scanner( "foo\\r\\nbar\\r\\n" );
    displayOptions();
    while ( running ) {
      String input = null;
      while ( scanner.hasNext() ) {
        input = scanner.next();
      }
      processInputCommand( input );
      running = false;
    }
  }

  abstract void displayOptions();

  abstract void processInputCommand( String input );

}

import java.rmi.RMISecurityManager;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class BasicClient extends AbstractClient {
  //private IBasicServer basicServer;

  public static void main( String[] args ) {
    new BasicClient();
  }

  public BasicClient() {
    try {
      System.setSecurityManager( new RMISecurityManager() );
      Registry registry = LocateRegistry.getRegistry();
      //basicServer =  (IBasicServer) registry.lookup(IBasicServer.LOOKUPNAME);
      run();
    } catch ( Exception e ) {
      e.printStackTrace();
    }
  }

  @Override
  void displayOptions() {
    //BasicClientOptions.displayOptions();
    System.out.println( "We're in subclasses displayOptions()." );
  }

  @Override
  void processInputCommand( String input ) {
    System.out.println( "We're in subclasses processInputCommand()." );
  }
}

我的输出

We're in subclasses displayOptions().
We're in subclasses processInputCommand().

所以实际上你的班级似乎正在工作,也许日志记录达不到标准。

希望这有帮助。

答案 3 :(得分:0)

这个帖子已经安静了一段时间,所以我怀疑这会对你有所帮助,但我想我会发布它以防其他人来寻找答案。

直到几分钟前,我遇到了与接口,抽象类和具体子类类似的问题。基本上,接口定义了10个方法,抽象类实现其中的2个,并为具体类留下另外8个。抽象类中的一个方法的实现调用一个本意由具体类实现的方法。

编译好的一切,NetBeans没有抱怨任何事情,但在运行时VM被轰炸出来,说明该方法(在具体类中实现的方法)不存在。自从我上次使用Java以来​​已经好几年了,但我很确定这不是这种情况下的预期行为(如果我错了,有人请纠正我。)

经过几个小时的踢我的笔记本电脑后,我发现添加一个抽象存根我正在调用抽象类的方法允许将调用转发到具体类而没有来自VM的任何抱怨。这是正常的还是我很幸运?

无论如何,希望有人觉得这很有用。