• 締切済み

このソースの間違えは・・・。

JAVAを始めてまだ間もない初心者です。以下のプログラムをコンパイルしたら、Testクラスのstrで”シンボルが見つかりません”となります。 なぜでしょうか?Outputクラスを継承させてるのに・・・。どなたか教えて下さい。後このプログラムをインターフェイス実装させる場合どう修正すべきでなんでしょうか?すいませんが、よろしくお願いいたします。 import java.io.*; class Output { public String message; public void setData(String str) { message = str; } public void display() { System.out.println(message + "と出力); } } class Monitor extends Output { public void display() { System.out.println(message + "とモニターに出力"); } } class Printer extends Output { public void display() { System.out.println(message + "とプリンターで印刷"); } } class HardDisk extends Output { public void display() { System.out.println(message + "とハードディスクに書く"); } } class Test { public static void main(String[] args) { try { BufferedReader br=      new BufferedReader(new InputStreamReader(System.in)); int num = Integer.parseInt(br.readLine()); int num = -1; while ((num < 0)||(num > 3)) { System.out.println("■処理を選択してください■"); System.out.print("0:画面に出力"); System.out.print("1:プリンタに出力"); System.out.print("2:ファイルに出力"); System.out.print("3:終了\n"); if ((num <= 2)&&(num >= 0)) { System.out.println("■出力する文字列を指定■"); } else if (num == 3) { System.out.println("終了しました"); System.exit(0); } else { System.exit(0); } } BufferedReader bw= new BufferedReader(new InputStreamReader(System.in)); num = Integer.parseInt(bw.readLine()); switch (num) { case 1: Monitor Moni = new Monitor(); Moni.setData(str); Moni.display(); break; case 2: Printer Pri = new Printer(); Pri.setData(str); Pri.display(); break; case 3: HardDisk Hard = new HardDisk(); Hard.setData(str); Hard.display(); break; default: System.exit(0); } } catch (Exception e) { System.out.println("ERROR"); } } }

みんなの回答

  • neko_noko
  • ベストアンサー率45% (146/319)
回答No.5

まずはOutputableインターフェースに必要な機能(メソッド)を考えます。 名前からすると、「データが出力可能であることをサポートする」ということだと思われますので、 データを出力する「output()」と、データをセットする「setData(String str)」が最低限必要です。 さらに、メッセージ出力のための「display()」も使われているので、 これを含めた3つのメソッドを抽象メソッドとして定義しておきます。 インターフェースの作成ができたので、OutputクラスにOutputableインターフェースを実装させます。 output()メソッドは抽象メソッドのままなということので、Outputクラス自体を抽象クラスにします。 あとはOutputクラスのサブクラスのMonitor、Printer、HardDiskの3つのクラスでoutput()メソッドを追加します。 こんなもんでしょうか。 こうしておけば、Testクラスのswitchの中で使用する変数Moni、Pri、Hardは Outputable型の変数で使いまわせます。

river_yos
質問者

お礼

できました!! 本当にわかりやすい回答ありがとうございました。 また近いうちに違う質問を新規で出してしまうかもしれませんが、見つけた時はお手数ですが、また回答頂けると嬉しいです。極力自分で限界までやってみたいと思います。 neko_nokoさん、そしてdriverIIさんありがとうございました。

  • driverII
  • ベストアンサー率27% (248/913)
回答No.4

そうですねぇ。 私だったら、MsgManager のようなクラスを作って、そこで全てやってしまうでしょうね(インターフェースを使わない)。現在の内容ではなにも複雑にすることはないでしょう。 これがもっと複雑になってきたら、質問のような形になるかもしれませんが、(現状では)setDataとdisplayを分ける必要もないですからね(例えば、display("hogehoge")のような形)。 とは言え、現在は実装は個人に任されていることが多いでしょう。 シンプルでかつ十分テストされたプログラムを心がければいいのではないでしょうか?(答えになっていなかったらすみません)

  • neko_noko
  • ベストアンサー率45% (146/319)
回答No.3

「インターフェースの実装」とありますが、これは、 このクラスに何か既存のインターフェースを実装させる、ということでしょうか? それともこのコードからインターフェースを抽出し、 そのインターフェースを利用したコードに書き換える、ということでしょうか? おそらく後者だと思われますが、 その場合、まずはどんなインターフェースを作成するかを考えると良いとおもいます。

river_yos
質問者

お礼

返信遅れて申し訳ありません。 抽象メソッドOutputを定義するインターフェイスOutputableを作成し Outputableをimplementsする形でOutputクラスを定義し直そうと思ってます。(Outputメソッドは抽象メソッドのまま)

  • driverII
  • ベストアンサー率27% (248/913)
回答No.2

Output ではメンバとして str を定義したわけではなく、 メソッド SetData の引数は String 型の変数で、このように利用します。ということを定義してあるだけです。 Test では str の定義がありません。 ここには文字列(String型)であれば何でも入ります。つまり、 String s; などで定義した s でも良いわけです。 そうすればコンパイラはこれは String 型と定義されている。SetDataの引数は String 型なので OK だな、と認識できるのです。 str ってなに型だ?というのが、質問のエラーだと思われます。

river_yos
質問者

お礼

非常にわかりやすく理解出来ました。ありがとうございます。 厚かましいお願いですが、インターフェースの実装はどうすべきでしょうか?

  • driverII
  • ベストアンサー率27% (248/913)
回答No.1

ざっと見た限りでは、 Output ではメソッドの引数に(String str)とされている。 Test クラスでは別に str の定義もせずいきなり setData(str)となっている。 String str を定義して、str に文字列を代入するのがやりたいことでは。

river_yos
質問者

お礼

すいません。補足に返答してしまいました。 早急な回答わざわざありがとうございます。 extendsで継承した場合に、Test クラスでまたString str を定義する必要はあるんですか?? すいません。初心者なもので・・・。

river_yos
質問者

補足

早急な回答わざわざありがとうございます。 extendsで継承した場合に、Test クラスでまたString str を定義する必要はあるんですか?? すいません。初心者なもので・・・。

関連するQ&A