前提
抽象クラスissueのサブクラスにBondクラスを加え、BondクラスのコンストラクタにIssueを引数とする段階でつまづいています。下記のエラー文が表示されるのはBondコンストラクタ引数のissueから何も検出されないため、Issueクラス内のコンストラクタと相違が生じるためでしょうか。また修正案などについてもご教授いただきたいです。よろしくお願いします。
同じディレクトリ内でenum型定義用のBondType.javaファイルも作成しているためソースを併せて添付しておきます。
実現したいこと
ここに実現したいことを箇条書きで書いてください。
- IssueをBondコンストラクタの引数として扱いたい。
発生している問題・エラーメッセージ
Issue.java:29: エラー: クラス Issueのコンストラクタ Issueは指定された型に適用できません。 public Bond (Issue issue, int maturity, double coupon) { ^ 期待値: String,String 検出値: 引数がありません 理由: 実引数リストと仮引数リストの長さが異なります
該当のソースコード
Issue.java
Java
1import java.util.Objects; 2 3public abstract class Issue { 4 private String code; 5 private String name; 6 7 public Issue (String code, String name) { 8 this.code = code; 9 this.name = name; 10 if (code == null || name == null) { 11 throw new IllegalArgumentException("nullです。"); 12 } 13 } 14 // getter 15 public String getCode() { 16 return this.code; 17 } 18 public String getName() { 19 return this.name; 20 } 21} 22 23 class Bond extends Issue { 24 private Issue issue; 25 private int maturity; 26 private double coupon; 27 private BondType type; 28 29 public Bond (Issue issue, int maturity, double coupon) { 30 this.issue = issue; 31 this.maturity = maturity; 32 this.coupon = coupon; 33 // チェック処理 34 if (maturity < 20000101 || 29991231 < maturity || coupon < 0) { 35 throw new IllegalArgumentException("数値が範囲外です"); 36 } 37 if (coupon == 0) { 38 type = BondType.ZERO_COUPON_BOND; 39 } else { 40 type = BondType.COUPON_BOND; 41 } 42 } 43 //getter 44 public Issue getIssue() { 45 return this.issue; 46 } 47 public int getMaturity() { 48 return this.maturity; 49 } 50 public double getCoupon() { 51 return this.coupon; 52 } 53 public BondType getBondType() { 54 return this.type; 55 } 56 57 @Override 58 public String toString() { 59 StringBuilder builder = new StringBuilder(); 60 builder.append(issue); 61 builder.append(maturity); 62 builder.append(coupon); 63 builder.append(type); 64 return builder.toString(); 65 } 66 67 //equalsメソッド 68 @Override 69 public boolean equals (Object obj) { 70 if (this == obj) { 71 return true; 72 } 73 if (obj == null) { 74 return false; 75 } 76 if (getClass() != obj.getClass()) { 77 return false; 78 } 79 Bond other =(Bond)obj; 80 if (this.issue != other.issue) { 81 return false; 82 } 83 if (maturity == 0) { 84 if (other.maturity != 0) { 85 return false; 86 } 87 } else if (maturity != other.maturity) { 88 return false; 89 } 90 if (Double.compare(other.coupon,coupon) != 0) { 91 return false; 92 } 93 94 return true; 95 } 96 97 //hashCode 98 @Override 99 public int hashCode() { 100 return Objects.hash(this.issue, this.maturity, this.coupon); 101 } 102}
BondType.java
public enum BondType { COUPON_BOND, ZERO_COUPON_BOND };
Bondのインスタンスは規定クラスとしての Issue インスタンスと フィールド issue の Issue インスタンスの2つを持つことになりますが、これは意図通りですか?
int32_t様
コメントありがとうございます。基底クラスのIssueのみをBondのコンストラクタに引数として渡す意図です。理解が追いついておらず的確な回答になっていなければ申し訳ございません。
うーん、質問を理解しておられないようです。
BondはIssueを継承しているので、Bondクラスにも getCode() getName() メソッドがありますが、これらは必要ですか? もし必要なら、どういう値を返すべきですか?
Issueの中にcode,nameが含まれているためgetterは必要だと考えていました。値に関してなんですが、Bondで使うようになるissueを返すようにするとかですかね?
Bond が Issue を継承している理由はなんでしょうか? Issue が1つも抽象メソッドを持っていないのに抽象クラスなのはなぜですか?
Issueをpublicな抽象クラス、BondクラスをIssueのサブクラスとするという問題に取り組んでいるためです。この段階では問題の途中経過であるため理由なくしているように見える箇所もあると思います。前提が不十分で申し訳ございません。
> Issueをpublicな抽象クラス、BondクラスをIssueのサブクラスとする
その場合、Bond のコンストラクタに Issue を渡すのではなく、Issue のコンストラクタの引数を渡すのが一般的かと。ちなみに、なにか参考にしている教科書とかありますか?
hoshi-takanori様
コメントありがとうございます。
BondをIssueの引数に渡し、Issue引数をcode,name,Bondにするという認識でしょうか。
教科書はやさしいjava第7版を使用しています。
継承の理解が怪しいですね。その本には Car と RacingCar の例が出てくるようですが、それを復習すると良いかと…。
Issue が abstract で、 Issue を継承したクラスが Bond しか無いのに、 Bond のコンストラクタにどうやって Issue オブジェクトを渡すつもりなのでしょうか。
通常はサブクラスのコンストラクタはスーパークラスのコンストラクタを呼ぶものですが、その辺りはどう理解されているのか…。
hoshi-takanori様
その例を見ながら取り組んでいたのでもう一度深く読み込んでみます。
その後、Issueコンストラクタの引数にBondを入れるよう修正したいと思います。
jimbe様
コメントありがとうございます。
正直abstractに関しては今回初めて用いるため知識不足が露骨に出てしまいました。
そのため、もう一度教科書を読み直した後おっしゃるようにサブクラスのコンストラクタをスーパークラスのコンストラクタに渡すよう修正してみます。
> サブクラスのコンストラクタをスーパークラスのコンストラクタに渡す
「コンストラクタを渡す」ということは出来ませんし、私はそのようには書いていませんが。
継承や抽象よりも先に「クラス」「オブジェクト」「コンストラクタ」を明確に分けて扱えないと、幾ら教科書・入門書を見ても teratail で説明されても理解が進まないと思います。
抽象クラスは必要にならないと中々分かり辛く、まして継承自体のイメージも出来上がっていなければ机上の勉強だけでは難しいと思います。
可能なら abstract は飛ばして、後から出てきたらもう一度でも二度でも戻ってくる風に臨機応変に (?) 学習を進めては如何でしょうか。
jimbeさんが御指摘されているように「抽象クラスはインスタンス化」できないため、
以下 Issueのことを「Issueのインスタンス」ではなく「Issue型のオブジェクト」と表記しています。
hoshi-takanoriさんが仰っている
[Bond のコンストラクタに Issue を渡すのではなく、Issue のコンストラクタの引数を渡す]は、
現状の"public Bond (Issue issue, ..... )"ように
Bond のコンストラクタの引数にIssue型のオブジェクト Issue issue を渡す
とするのではなく、
> Issueクラス のコンストラクタ"Issue (String code, String name)"の引数である(String code, String name)を渡す
つまり
public Bond (Issue issue, int maturity, double coupon)
を
public Bond (String code, String name, int maturity, double coupon)
にするということかと思います。
この場合、int32_tさんの回答の
super(issue.getCode(), issue.getName());の部分が
super(code, name);になりますね
BondのコンストラクタでIssue型のオブジェクトを引数にするという指定がないのであれば、こちらのほうが自然に感じます。
理解できたのなら質問を閉じてください。まだ未解決扱いですよ。
すでについている回答で理解できたならその回答をベストアンサーにし、自分で深掘りしたとかで解決したなら「自己解決」的なやつがあるはずなのでそこに『どういう風に解決したか』みたいなものを書いてください。お願いします。
jimbe様
知識不足により解釈を誤ってしまい申し訳ございません。
諸事情でこのabstractの課題を最優先で取り組む必要があるので今一度『クラス』等から復習させていただきたいと思います。
> abstractの課題を最優先で取り組む必要がある
ナカナカ厄介な状況のようで ><
Crimson_Tide様
とても丁寧な解説ありがとうございます。
引数を渡すということだったのですね。とても大きな勘違いをしていました。
設問に「Issueクラスのコンストラクタを使ってBondクラスのコンストラクタを定義する」とあるのですが、この文が自分の中で明確に理解できていないため、今回しどろもどろな感じになっている気がします。この設問の場合は 「BondのコンストラクタでIssue型のオブジェクトを引数にする指定」はないことになるのでしょうか。「コンストラクタを使って」という箇所が「コンストラクタの引数を使って」と解釈していいのか気になります。
BeatStar様
ご指摘ありがとうございます。
最初の質問自体はコンパイルが通り解決したのですが、他の方々のご意見をいただき質問とは別の箇所に疑問を抱いたため、ご意見をいただきたく質問を閉じていませんでした。
この場合普通は質問を閉じるべきなのでしょうか。
jimbe様
そもそもこの課題に至るまで曖昧な解釈で課題をクリアできていたことに問題があると思います。
この課題で改めて知識不足を実感させられたため、一度復習する機会を得たと思って復習からしていきたいと思います!
> 設問に「Issueクラスのコンストラクタを使ってBondクラスのコンストラクタを定義する」
それは、私の回答にあるような super() 呼び出しのことです。引数にしろという意味ではありません。
回答2件