- ベストアンサー
初心者ですがコンストラクターについて質問
swingを現在勉強中なのですが、とりあえずコンポーネントを作成する部分で、以下のようなソースを書きました。 JPanel p1 = new JPanel(); p1.setPreferredSize(new Dimension(100, 100)); Border border = new BevelBorder(BevelBorder.RAISED); p1.setBorder(border); 4行目ですが、コンストラクターを呼び出してインスタンス化する場合にBorderオブジェクト型になっているのですが、素人の私には BevelBorder bevelborder = new BevelBorder(BevelBorder.RAISED); にならないのはなぜ?と思ってしまいます。APIをみればsetBorderメソッドがBorderオブジェクトを引数にもつ事は理解できますが、コンストラクターの部分はいまいち理解できません。初歩的な質問ですが、教えていただけないでしょうか?
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
>インスタンス化とキャストを同時にしている その理解でよいと思いますが、細かいことが気になる方だと見受けましたので、ご参考までに「Java言語規定」での定義に従うと、厳密には: Border border = (Border)bevelborder; これは「キャスト変換」 http://www.y-adagio.com/public/standards/tr_javalang/5.doc.htm#20232 Border border = new BevelBorder(BevelBorder.RAISED); これは「代入変換」 http://www.y-adagio.com/public/standards/tr_javalang/5.doc.htm#170768 BevelBorder bevelborder = new BevelBorder(BevelBorder.RAISED); これは「メソッド呼出し変換」 http://www.y-adagio.com/public/standards/tr_javalang/5.doc.htm#12687 となると思います。 >BevelBorderクラスはBorderクラスのサブクラス 「BevelBorderクラスはBorderインタフェースを実装する」が、正確な表現です。 >これはAbstractBorderにimplementsされているので実際には >AbstractBorder内のBorderクラスでキャストしている事になるのですか 「AbstractBorder内のBorderクラス」という表現が若干気になりますが、多分理解されています。 ご参考までに、これも「Java言語規定」の「スーパインタフェース」 http://www.y-adagio.com/public/standards/tr_javalang/8.doc.htm#34031 に従うと、 ・BorderインタフェースはAbstractBorderクラスの「直接的スーパインタフェース」である ・AbstractBorderクラスはBevelBorderクラスの「直接的スーパクラス」である したがって、 ・BorderインタフェースはBevelBorderクラスの「スーパインタフェース」である すなわち ・BevelBorderクラスはBorderインタフェースを実装する となるかと思います。 上記「代入変換」の頁には以下のように書いてありますので、変換が可能という結論になります。 引用開始>>>> コンパイル時参照型 S(代入元)の値のコンパイル時参照型 T(代入先)への代入は,次のように検査する。 (中略) T がインタフェース型ならば, T は S と同じインタフェース又は S のスーパインタフェースでなければならない <<<<引用終了 TがBorder、SがBevelBorderですね。 ・・・と、くどくどと書きましたが、 BevelBorderはBorderである(is-a関係) わけですから、Border型の変数にBevelBorderのインスタンスが突っ込まれることは極自然なことです。 逆の場合はそうとは限りません(BorderはBevelBorderとは限らない)ので、明示的なキャスト変換が必要になります。代入変換やメソッド呼出し変換はできません。 BevelBorder bevel = (BevelBorder)border;//borderはBorder型
その他の回答 (2)
- kztk
- ベストアンサー率53% (59/110)
#2です。コピペミスのため、訂正します。 >BevelBorder bevelborder = new BevelBorder(BevelBorder.RAISED); >これは「メソッド呼出し変換」 正しくは、 BevelBorder bevelborder = new BevelBorder(BevelBorder.RAISED); p1.setBorder(border); これは「メソッド呼出し変換」
Border border = new BevelBorder(BevelBorder.RAISED); BevelBorder bevelborder = new BevelBorder(BevelBorder.RAISED); どっちでもいいです。好きにしてください。 setBorderするのは、Borderクラス(またはそれを継承したクラス)です。で、BevelBorderはBorderクラスを継承して作ったサブクラスです。 ですから、これは単純に「BevelBorderを変数に収める際にBorderにキャストしてからsetBorderする」か、あるいは「BevelBorderを変数に収め、setBorderする際にBorderにキャストする」か、どっちかということです。以下のような感じですね。 Border border = new BevelBorder(BevelBorder.RAISED);←ここでキャスト p1.setBorder(border); BevelBorder bevelborder = new BevelBorder(BevelBorder.RAISED); p1.setBorder(border);←ここでキャスト どっちにしろ、要するに「BevelBorderをどこかでBorderにキャストしてsetBorderする」ということに変わりはありません。
補足
ご教授有難うございました。 以下実行して正常に動作しました。 BevelBorder bevelborder = new BevelBorder(BevelBorder.RAISED); Border border = (Border)bevelborder; p1.setBorder(border); 言われるとおり、インスタンス化とキャストを同時にしている事がよくわかりました。確かにBevelBorderクラスはBorderクラスのサブクラスですね。あともう少し教えて頂きたいのですが、APIをみるとBorderクラスはinterfaceクラスです。これはAbstractBorderにimplementsされているので実際にはAbstractBorder内のBorderクラスでキャストしている事になるのですか?それともクラスのキャストは別にinterfaceだとかはあまり気にしないでクラスはクラスということなのでしょうか?ど素人なのでとんでもない事をいってるかも知れませんが、よろしくお願いします。
お礼
親切ご教授して頂き有難うございました。 納得いく説明でしたのですっきりしました。 文中の参考urlをもとにもっと勉強してみます。