質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

4回答

10231閲覧

あるクラスのフィールドに任意の値を代入して参照したいです

退会済みユーザー

退会済みユーザー

総合スコア0

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2017/06/19 08:17

編集2017/06/19 08:32

Heroクラスのattackメソッドでmonster.nameを参照したいのですがデフォルトコンストラクタの初期値であるnullとなってしまい同様にmonster.hp0となります。Goblinクラスのrunメソッドのthis.nameゴブリンを参照できているので指定の方法が悪いのでしょうか?

java

1null6ダメージを与えた 2-6 3ゴブリン Aは、必死に逃げ出した! 4ゴブリン Bは、必死に逃げ出した!

上の結果のnullGoblin Aと表示させたうえで現在のhpからランダムで算出した値を引いてダメージ計算をしたいです。Goblinクラスをインスタンス化してnamehpに値を代入したあと参照するにはどうすればいいのでしょうか?

java

1public class Hero { 2 int hp; 3 String name; 4 5 public int attack(Monster monster) { 6 int damage = (int) (Math.random() * 10); 7 System.out.println(monster.name + "に" + damage + "ダメージを与えた"); 8 9 int monsterHpNow = monster.hp - damage; 10 11 return monsterHpNow; 12 } 13}

java

1public abstract class Monster { 2 int hp; 3 String name; 4 5 public abstract void run(); 6}

java

1public class Goblin extends Monster { 2 String name = "ゴブリン"; 3 int hp = 10; 4 5 public Goblin(String name) { 6 this.name = this.name + " " + name; 7 } 8 9 public void run() { 10 System.out.println(this.name + "は、必死に逃げ出した!"); 11 } 12}

java

1public class Main { 2 3 public static void main(String[] args){ 4 Goblin goblinA = new Goblin("A"); 5 Monster goblinB = new Goblin("B"); 6 Hero hero = new Hero(); 7 8 int testPrint = hero.attack(goblinA); 9 System.out.println(testPrint); 10 goblinA.run(); 11 goblinB.run(); 12 } 13}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

swordone

2017/06/19 08:29

実行しているメインクラスを載せてください。
退会済みユーザー

退会済みユーザー

2017/06/19 08:32

すみません載せるのを忘れていました。追記しました。
guest

回答4

0

Monsterクラスのnameが未設定なのでnullが出力されます。

public Goblin(String name) { this.name = this.name + " " + name; super.name = this.name; }

にすると、Hero#attack() で、名前が出るようになりますが・・・

yonaさんの回答のように、getNameの定義とサブクラスでのオーバーライドが良いです。
あと、run は、Javaだと予約語というか、スレッド開始のメソッド用なのでrunaweyとかescape的な
別の名前のほうが良いです。

投稿2017/06/19 08:47

momon-ga

総合スコア4820

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/06/19 09:51

runは既にあったんですね。今度から他の名前にします。Monsterクラスで定義しなければならないのも勉強になりました。
guest

0

親クラス(Monster)でも子クラス(Goblin)でも同名のメンバ変数を宣言しているので対象の変数がどちらのものかわかりにくくなっています。

java

1public class Goblin extends Monster { 2 3 public Goblin(String name) { 4 this.name = "ゴブリン " + name; 5 this.hp = 10; 6 } 7 8 public void run() { 9 System.out.println(this.name + "は、必死に逃げ出した!"); 10 } 11}

最小限の変更で対応するならこんな感じでしょうか。

投稿2017/06/19 08:34

tkturbo

総合スコア5572

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/06/19 09:51

親クラスで定義したいと思います。ありがとうございました
guest

0

ベストアンサー

Monster, Goblin両方にnameという同名のフィールドが定義されている場合、

java

1Monster monster = new Goblin("A"); 2System.out.println(monster.name);

のようにMonsterクラスの型の変数を通じてnameにアクセスすると、実際のクラスがGoblinであってもMonsterクラスのnameフィールドが参照されます。hpも同様です。メソッドはoverrideできるのですがフィールドはoverrideできないのです。

解決策としてお勧めなのは、同じ意味を持ったフィールドは基底クラスにのみ宣言することです。

java

1public abstract class Monster { 2 String name; 3 int hp; 4 5 // コンストラクターを通じてしかインスタンスの生成を許さなようにする 6 protected Monster(String name, int hp) { 7 assert name != null; // 誤った初期化をデバッグ時にすぐ気づけるようにする 8 assert hp > 0; // 誤った初期化をデバッグ時にすぐ気づけるようにする 9 this.name = name; 10 this.hp = hp; 11 } 12} 13 14public class Goblin extends Monster { 15 static final int INITIAL_HP = 10; 16 17 public Goblin(String name) { 18 super("ゴブリン " + name, INITIAL_HP); // 必ず基底クラスのコンストラクターを呼ぶ 19 } 20}

投稿2017/06/19 08:33

編集2017/06/19 08:35
KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/06/19 09:52

なんとなくメソッドと同じようにフィールドもオーバーライドできる感覚でいました。試してみたところ基底クラスでの宣言でうまくいきました。ありがとうございます。
guest

0

メインメソッドが無いのでクラスの使い方を間違っている可能性がありますね。

とりあえず下記のような変更をするといいと思いますよ。
・Monsterクラスにnameとhpを設定するコンストラクタが必要ですね。
・Monsterクラスに抽象メソッドgetNameを定義しましょう。
・GoblinクラスのコンストラクタでMonsterクラスのコンストラクタを呼びましょう。
・Goblinクラスにはnameとは別にAやB等のpostfix変数を定義すべきですね。
・GoblinクラスでgetNameを実装し、結合した名前を返却しましょう。以降はこのメソッドを使って名前を取得しましょう。

投稿2017/06/19 08:32

yona

総合スコア18155

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/06/19 09:55

メインメソッドの記載を忘れていました。すみません。 postfix変数というのは初耳なので調べてみます。getNameの定義と子クラスのコンストラクタで親クラスのコンストラクタを呼ぶ練習をしてみます。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問