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

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

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

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

Q&A

解決済

1回答

2565閲覧

個々のインスタンスに番号を振りたいです。サブクラスの扱い方等、、

shimajiro1917

総合スコア4

Java

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

0グッド

1クリップ

投稿2021/01/05 10:17

編集2021/01/06 12:34

前提・実現したいこと

各インスタンスに格納される数値に番号をつけたいです。

色々な図形の大きさを設定して面積を求めるメソッドを含むサブクラスを作りました。それらを使って別のクラスに各図形の面積を表す文字列を乱数発生させてコンソールに表示させたいのです。その際に各図形の面積にNo.1... のように番号を振りたいです。

各図形の面積に関するサブクラスは

java

1package object; 2 3public class Circle1 extends Figure { 4 private double radius = 0; 5 6 Circle1(){ 7 this.radius = 20; 8 } 9 public Circle1() { 10 // TODO 自動生成されたコンストラクター・スタブ 11 } 12 void Circle(double r){ 13 this.radius = r; 14 } 15 void setRadius(double r) { 16 } 17 void setSize(double r) { 18 setRadius(r); 19 } 20 double getRadius() { 21 return this.radius; 22 } 23 @Override 24 double getArea() { 25 area = Math.PI * this.radius * this.radius; 26 return area; 27 // TODO 自動生成されたメソッド・スタブ 28 } 29 void identify() { 30 System.out.println("I am a Circle1 with area" + getArea() + "and" + getNumber() + "."); 31 // TODO 自動生成されたメソッド・スタブ 32 33 } 34 private String getNumber() { 35 // TODO 自動生成されたメソッド・スタブ 36 return null; 37 } 38 @Override 39 void iduntify() { 40 // TODO 自動生成されたメソッド・スタブ 41 42 } 43 44}

と、同様にRectangle、Square、Triangleを作成しています。

複数のサブクラスに渡って番号をふることができません。

実行したいクラスのコードは以下のようです

エラーメッセージ
「暗黙的スーパー・コンストラクターFigure()は未定義です。別のコンストラクターを目地的によびだす必要があります。」
と表示されますが、どういうことなのかいまいちよくわかりません。

該当のソースコード

java

1package object; 2 3public class Figures{ 4 public static void main(String[] args) { 5 Figure[] figures1 = new Figure[9]; 6 Figure[] figures2 = new Figure[9]; 7 Rectangle r1 = new Rectangle(); 8 Rectangle r2 = new Rectangle(30, 20); 9 int i = 0; 10 11 System.out.println("The area of r1 is" + r1.getArea()); 12 System.out.println("The area of r2 is" + r2.getArea()); 13 14 r1.setWidth(40); 15 r1.setHeight(30); 16 System.out.println("The area of r1 is" + r1.getArea()); 17 18 r2.setSize(60, 40); 19 System.out.println("The area of r2 is" + r2.getArea()); 20 21 figures1[i++] = r1; 22 figures1[i++] = r2; 23 24 Circle1 c1 = new Circle1(); 25 Circle1 c2 = new Circle1(20); 26 figures1[i++] = c1; 27 figures1[i++] = c2; 28 System.out.println("The area of c1 is" + c1.getArea()); 29 System.out.println("The area of c2 is" + c2.getArea()); 30 31 Triangle t1 = new Triangle(3, 5); 32 Triangle t2 = new Triangle(30, 20); 33 Triangle t3 = new Triangle(300, 200); 34 System.out.println("The area of t1 is" + t1.getArea()); 35 System.out.println("The area of t2 is" + t2.getArea()); 36 System.out.println("The area of t3 is" + t3.getArea()); 37 38 figures1[i++] = t1; 39 figures1[i++] = t2; 40 figures1[i++] = t3; 41 42 Square2 s1 = new Square2(); 43 Square2 s2 = new Square2(20); 44 System.out.println("The area of s1 is " + s1.getArea()); 45 System.out.println("The area of s2 is " + s2.getArea()); 46 47 figures1[i++] = s1; 48 figures1[i++] = s2; 49 50 System.out.println(); 51 for(int j=0; j<figures1.length; j++) { 52 figures1[j].iduntify(); 53 } 54 55 System.out.println(); 56 i = 0; 57 for (int j=0; j<figures2.length; j++) { 58 figures2[j] = figures1[choose()]; 59 } 60 for (int j=0; j<figures2.length; j++) { 61 figures2[j].iduntify(); 62 } 63 } 64 static int choose() { 65 int x = (int)(Math.random()*9); 66 return x; 67 } 68 69 70}

試したこと

スーパークラスに

java

1package object; 2 3public abstract class Figure { 4 double area = 0; 5 abstract double getArea(); 6 abstract void iduntify(); 7 void identify() { 8 // TODO 自動生成されたメソッド・スタブ 9 } 10 public static void main(String[] args) { 11 int[] array = new int[10]; 12 for(int i=0;i<=array.length;i++) { 13 array[i]=i+1; 14 } 15 } 16}

というコードを書いてみました。

補足情報(FW/ツールのバージョンなど)

初心者なので用語の正しい定義を理解していない部分があるかと思います。いくつもクラスが分かれてしまって自分でもよくわからなくなってしまったので、同じようなコードを作成したことがある方がいらっしゃいましたら何かアドバイスがいただけたら幸いです、、、

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

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

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

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

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

BeatStar

2021/01/05 11:49

Circleのコンストラクタ( int i を引数にとっている方 ) 必要ですかね? 引数使っていないんですが…
shimajiro1917

2021/01/05 12:51

何かのエラーメッセージにしたがって何度も直していたらそうなっていたようです! (int i)は不要ですね、ありがとうございます。
BeatStar

2021/01/06 07:56

あと、修正してください。 修正時に "<コード>" (あるいは "<code>" となっている) のボタンを押して、その中に書いてください。 このままだと、インデントが無視されるので、非常に読みづらいです。 読む気も失せます。
shimajiro1917

2021/01/06 12:48

すみません、初めてこのサイトを利用したので書き方がわからず読みづらい投稿をしてしまいました。 修正しました。
guest

回答1

0

ベストアンサー

色々な考え方、作り方があるかと思いますが、Figureクラスを継承したクラスのインスタンスごとに一意なID(すなわちインスタンス番号)を振りたいとすると、ベースとしたFigureクラスで一意の番号を生成するクラスのstaticフィールドを用意し、Figureクラスを継承したクラスのインスタンス生成時にそのメソッドで呼び出し、実際の値を割り当てる、という考え方で実装することができます。

インスタンス番号を生成するものとしては、単純に1から始めてインスタンス生成時に+1していくようなクラスを用意すれば良い訳ですが、雑に作るとマルチスレッド、並列プログラミングのような場合に正しくインスタンス番号を生成できないことがあります。勉強の為の習作であればそれでも良いでしょうか、質問者さんの後の質問
stackとqueueの実行エラーについて - teratail#314536
などでは既に java.util.concurrent.atomic.AtomicInteger を使おうと言う意思があるので、こちらが適切でしょう。本回答でもそれで例を示します。

まず、Figureクラスを継承したクラスのインスタンス全体として一意とするとために、staticフィールドとしてAtomicIntegerを追加します。FigureクラスではJavaの構文である「初期化子(initializer)」を利用して、個々のインスタンス生成時にaddAndGet()メソッドで更新した値をそのinstanceNumberフィールドにセットします。初期化子を使うことでFigureクラスを継承したクラスでは特にコンストラクタ内で改めて初期化せずとも、自動的にinstanceNumberフィールドが初期化されることとなり、好都合です。

Java

1// Figure.java 2package object; 3 4import java.util.concurrent.atomic.AtomicInteger; 5 6abstract class Figure { 7 // Figureクラスを継承したクラスのインスタンスで一意の番号(インスタンス番号) 8 // とする為、クラスフィールドにする。 9 private static final AtomicInteger counter = new AtomicInteger(0); 10 11 // 個々のインスタンスの番号 12 private final int instanceNumber; 13 14 // 初期化子(initializer)で初期化する。 15 { 16 instanceNumber = counter.addAndGet(1); 17 } 18 19 double area = 0; 20 21 abstract double getArea(); 22 abstract void identify(); 23 24 public int getNumber() { 25 return this.instanceNumber; 26 } 27}

上記例では初期化子を使わずともprivate final int instanceNumber = counter.addAndGet(1);でも大丈夫です。初期化子では{}内でコンストラクタのように複数の処理を記述できるので、適時、使い分けてください。

次に、抽象クラスであるFigureを継承したRectangleCircle1クラスを示します。ソースコードを簡単にするために Main.java内に一緒に定義します。

Java

1// Main.java 2package object; 3 4class Rectangle extends Figure { 5 private double height = 0; 6 private double width = 0; 7 8 Rectangle(){ 9 this.width = 20; 10 this.height = 10; 11 } 12 13 Rectangle(double width, double height){ 14 this.width = width; 15 this.height = height; 16 } 17 18 @Override 19 double getArea() { 20 return width * height; 21 } 22 23 @Override 24 void identify() { 25 System.out.println("I am a Rectangle(instance number=" + getNumber() + ") with area " + getArea() + "."); 26 } 27} 28 29class Circle1 extends Figure { 30 31 private double radius = 0; 32 33 Circle1() { 34 // this.radius = 20; 35 // オーバーロード版 Circle1(double r)を呼ぶことも可能 36 this(20); 37 } 38 39 Circle1(double r){ 40 this.radius = r; 41 } 42 43 @Override 44 double getArea() { 45 area = Math.PI * this.radius * this.radius; 46 return area; 47 } 48 49 @Override 50 void identify() { 51 System.out.printf("I am a Circle(instance number=%d) with area %f.\n", getNumber(), getArea()); 52 } 53} 54 55public class Main { 56 public static void main(String[] args) { 57 58 Figure[] figures1 = new Figure[4]; 59 int i = 0; 60 61 Rectangle r1 = new Rectangle(); 62 Rectangle r2 = new Rectangle(40, 30); 63 System.out.println("The area of r1 is " + r1.getArea()); 64 System.out.println("The area of r2 is " + r2.getArea()); 65 figures1[i++] = r1; 66 figures1[i++] = r2; 67 68 Circle1 c1 = new Circle1(); 69 Circle1 c2 = new Circle1(30); 70 System.out.println("The area of c1 is " + c1.getArea()); 71 System.out.println("The area of c2 is " + c2.getArea()); 72 figures1[i++] = c1; 73 figures1[i++] = c2; 74 75 for (int j = 0; j < figures1.length; j++) { 76 figures1[j].identify(); 77 } 78 } 79}

これをWindowsのコマンドプロンプト上で実行すると、以下のようになります。インスタンス番号が1から始まり、RectangleCircle1のそれぞれのインスタンスに割り当てられていることが分かります。実行例はJava SE 11ですが、Java SE 8でも同様の結果となります。

CMD

1C>java -version 2java version "11.0.9" 2020-10-20 LTS 3Java(TM) SE Runtime Environment 18.9 (build 11.0.9+7-LTS) 4Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.9+7-LTS, mixed mode) 5 6C>javac object\Main.java 7 8C>java object.Main 9The area of r1 is 200.0 10The area of r2 is 1200.0 11The area of c1 is 1256.6370614359173 12The area of c2 is 2827.4333882308138 13I am a Rectangle(instance number=1) with area 200.0. 14I am a Rectangle(instance number=2) with area 1200.0. 15I am a Circle(instance number=3) with area 1256.637061. 16I am a Circle(instance number=4) with area 2827.433388. 17 18C>

一応指摘しておきますと、インスタンス番号の更新に使うAtomicIntegerクラスのaddAndGet(1)は単純に+1するだけなので、intの最大値である0x7fffffffを越えると桁あふれを起こして値が正負と共にでんぐり返ります。コードが勉強の為の習作であるならば特に問題にはならないはずですが、もしインスタンス番号をファイルに保存するなどして永続化を計るような製品のコードの場合は更に検討が必要になるはずなので、将来の為に頭に留め置くと良いです。

投稿2021/01/08 00:52

dodox86

総合スコア9183

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

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

shimajiro1917

2021/01/08 13:43

とてもご丁寧にありがとうございます。親クラスのシンプルなコードで動いて感動しました、、とても勉強になりました。dodox86さんのようなコードが書けるようにがんばります! 長々と質問にお付き合いいただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問