3

だから私は2つのクラスがあります。1つは抽象的です:

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

}

1つは具体的なサブクラスです。

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()内にprintステートメントを入れて、呼び出したメソッドで何かしらなことをしていないことを確認しました。

どうもありがとう、

アダム

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

クラスが異なるパッケージに入っているということですか? その場合は、オーバーライドするメソッドを保護されていると宣言する必要があります。

編集:(説明が役立つと思います:-)

メソッド public/protected を宣言すると、パッケージ外の子によってオーバーライドされる可能性があります。(パッケージ)/プライベートにすると、できません。プライベート メソッドはまったくオーバーライドできません。どの (パッケージ) メソッドは、同じパッケージ内のクラスによってのみオーバーライドできます。

(パッケージ) を使用するのは、キーワードがないためです。したがって、public/protected/private がない場合は、(パッケージ) アクセスを取得します。

編集:

あなたの説明を考えると、上記は当てはまらない可能性があります(クラスが実際に抽象的であり、 @Override アノテーションを使用したと仮定します)。

run メソッドが呼び出されていることを 100% 確信していますか? System.out.println を実行して、それが呼び出されることを確認します。

他の例外をキャッチしておらず、スタック トレース (または、例外がキャッチされたことを確認するための何か) の出力に失敗していないことを 100% 確信していますか?

于 2009-03-15T03:20:23.813 に答える
0

問題が何であるかわからないので、(printステートメントを使用して)出力を印刷できますか?

私はあなたのコードをコピー/貼り付けし、オブジェクトの適切なソースがなかった1、2行をコメントアウトする以外に。それは私のためにサブクラスメソッドを呼び出しました。

論理的には、コードを読むのに違和感はありませんでしたが、別の問題がないことを確認するために自分の目で何かを見るのが好きなので、最初にコードを実行してみました。:)

これが私が変更したものと私の出力です。

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 に答える
0

このスレッドはしばらく静かだったので、これがあなたに役立つとは思えませんが、誰かが答えを探しに来た場合に備えて投稿したいと思いました。

数分前まで、私はインターフェース、抽象クラス、および具象サブクラスで同様の問題を抱えていました。基本的に、インターフェイスは10個のメソッドを定義し、抽象クラスはそのうちの2つを実装し、残りの8つを具象クラスに残します。抽象クラスのメソッドの1つの実装は、具象クラスによって実装されることを意図したメソッドを呼び出します。

すべてが正常にコンパイルされ、NetBeansは何も文句を言わなかったが、実行時にVMが爆破し、メソッド(具象クラスに実装されたもの)が存在しないと述べた。前回Javaを使用してから何年も経ちますが、これはこの状況で予想される動作ではないと確信しています(間違っている場合は誰かが訂正してください)。

ラップトップを数時間キックした後、呼び出していたメソッドの抽象スタブを抽象クラスに追加すると、VMからの苦情なしに呼び出しを具象クラスに転送できることがわかりました。これは正常ですか、それとも私は幸運に恵まれましたか?

とにかく、誰かがこれが役に立つと思うことを願っています。

于 2009-09-30T19:30:51.353 に答える