2009-03-15 3 views
3

私は2つのクラスを持っています。一つは、抽象的です:Java抽象クラスの混乱:オーバーライドされたメソッドが呼び出されていない

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

たぶん何かがあなたの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"); 
    } 
} 
0

わからない、あなたは(あなたのprint文で)いくつかの出力を印刷することができます。

私はあなたのコードをコピーして貼り付けましたが、私がdid'ntした行をコメントアウトするのとは別に、オブジェクトの正しいソースがあります。私のためにサブクラスメソッドを呼び出しました。

論理的には、コードを読み取っても何の問題もないように見えましたが、別の問題がないことを自分の目で確認してコードを実行しようとしました。 :)

ここに私が変更したものと、私の出力があります。

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

だから、実際には、それはあなたのクラスは、ロギングはパーまでなかっただけかもしれない仕事をしていたようです。

これが役に立ちます。

+0

コメントは、私があるようTEHスキャナを残し、任意の入力は文句を言わないrighty離れて呼び出すことが)のでprocessInputCommandを(ブロックする持っていないことを追加する必要があります。だからこそ私はあなたのスキャナを、\\ \ n \ bar \ r \ nをそれにハードコーディングしていた。デモのための詳細。 申し訳ありません。 –

2

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

編集:(説明は、メソッドの公開/保護を宣言すると、それはパッケージの外側子供で上書きすることができ

:-)役立つかもしれないと思います。あなたがそれを(パッケージ)/プライベートにするなら、それはできません。プライベートメソッドをオーバーライドすることはできません。(パッケージ)は、同じパッケージ内のクラスによってのみオーバーライドできます。

そのためのキーワードが存在しないため、プライベート/保護/公共の不存在下であなたが(パッケージ)アクセスを得るので、私は、(パッケージ)を使用します。

編集:

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

実行方法が呼び出されていることを100%確信していますか? System.out.printlnを実行し、呼び出されていることを確認します。

は、あなたが他の例外をキャッチし、(あなたは例外がキャッチされたことを見ていることを確認しますまたは他の何か)スタックトレースをプリントアウトして失敗していないことが100%か?

+0

TofuBeer - あなたが正しいです。人々はjavaのデフォルトの保護に注意を払う必要があります! – Pat

0

このスレッドはしばらく静かになっているので、私は、これはあなたを助ける疑うが、私は他の誰かが答えを探してきた場合にそれを投稿しようと思いました。

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

すべては何も文句ありませんでしたが、実行時にVMは、方法(具象クラスで実装1)が存在しなかったことを示す、アウト爆撃しました。 Javaを最後に使ってから何年も経っていますが、これが期待された動作ではないことは間違いありません。

私のラップトップを蹴る数時間後、抽象クラスに呼び出すメソッドの抽象的なスタブを追加すると、VMからの苦情なしにコールがコンクリートクラスに転送されることがわかった。これは正常なのですか、それとも私はただ幸運になりましたか?

とにかく、誰かがこれを見つけることを願っています。私自身の投稿に

+0

それは正常ではありません。何かが正しくコンパイルされなかったようです。実行時に古いバージョンのインターフェースがあったとします。抽象クラスにメソッドを追加することで、実行時に古いバージョンのインターフェースを持っていても問題は解決しました。 – Yishai

関連する問題