3

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

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() 所以我假设它会调用子类方法,但它似乎没有。有没有办法做到这一点,或者我犯了一个明显的错误,或者我误解了抽象类应该如何工作?

PS 我尝试在子类 displayOptions() 中放置一个打印语句,以确保我没有用我调用的方法做一些愚蠢的事情。

非常感谢,

亚当

4

4 回答 4

5

你的电话可能有问题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");
    }
}
于 2009-03-15T00:42:36.343 回答
2

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

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

如果您声明一个公共/受保护的方法,那么它可以被包外的子级覆盖。如果您将其设为(包)/私有,则它不能。私有方法根​​本不能被覆盖,哪些(包)方法只能被同一个包中的类覆盖。

我使用 (package) 是因为它没有关键字,所以在没有公共/受保护/私有的情况下,您可以获得 (package) 访问权限。

编辑:

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

你 100% 确定 run 方法被调用了吗?运行 System.out.println 并确保它被调用。

您是否 100% 确定您没有捕获任何其他异常并且未能打印出堆栈跟踪(或其他可以确保您看到异常已被捕获的东西)?

于 2009-03-15T03:20:23.813 回答
0

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

直到几分钟前,我还在接口、抽象类和具体子类方面遇到了类似的问题。基本上,接口定义了 10 个方法,抽象类实现其中的 2 个,而将另外 8 个留给具体类。抽象类中的一种方法的实现调用了一个本应由具体类实现的方法。

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

经过几个小时的使用笔记本电脑后,我发现将我正在调用的方法的抽象存根添加到抽象类可以将调用转发到具体类,而不会受到 VM 的任何抱怨。这是正常的还是我运气好?

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

于 2009-09-30T19:30:51.353 回答
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().

因此,实际上,您的班级似乎正在工作,只是日志可能没有达到标准。

希望这可以帮助。

于 2009-03-15T00:52:21.670 回答