「オブジェクト志向」の考えかたで質問します

このQ&Aのポイント
  • 「オブジェクト志向」の考えかたを調べた結果、繼承、カプセル化、ポリモーフィズムを総称したものだと理解しました。
  • 具体的な例として、指定するクラスの生徒の情報を取得するソースを作成したいです。
  • 作成したソースは、実行DAOクラス、StudentDAO、DB接続クラス、Beanクラスの4つで構成されます。
回答を見る
  • ベストアンサー

「オブジェクト志向」の考えかたで質問します。

「オブジェクト志向」の考えかたで質問します。 いろいろと調べると、 ・繼承 ・カプセル化 ・ポリモーフィズム を総称したのが、「オブジェクト」志向と理解しています。 このとき、 たとえば、 指定するクラスの生徒の情報をとりだすようなソースをつくりたい。 仮に、以下をかんがえてみました。 DB処理は、省いてます。 //実行DAOクラス public class StudentDAO extends StudentDBAccessor{ //指定するクラスに属する生徒をとりだす public List getStudentList(int classNumber){ return super.getStudentList(); } //sql文生成 protected String createSqlSelectStudentList(){ StringBuffer sb = new StringBuffer(); return sb.toString(); } //キーワードを設定 public void setDataSqlStudentList(){ } } public abstract StudentDBAccessor extends DBConnector{ protected List getStudentList(){   //DBそうさ } protected abstract String createSqlStudentList(); protected void setDataSqlStudentList(int classNumber); } //DB接続クラス public class DBConnector{   //省略 } //Beanクラス public class StudentFormBean{ private int studentNumber; private String studentName; public void setStudentNumber(int number){ this.studentNumber = number; } public int getStudentNumber(){ return studentNumber; } } よろしくおねがいします。

  • Java
  • 回答数7
  • ありがとう数7

質問者が選んだベストアンサー

  • ベストアンサー
  • hoge_piyo
  • ベストアンサー率57% (15/26)
回答No.7

コレクションというのは、List,ArrayList, Set,HashSet etc...の亊を言うのでしょうか? そうです。 List<Human> heightList = new ArrayList<Human>(new HeightComparator()); の系式で表す亊はできるのでしょうか? ArrayListではできません。 このときのアルゴリズムをいれかえる動作というのは、 ソースでいうと、・・・の部分の亊をいうのでしょうか? そうです。 一方、これをListでも実現する亊はできるのでしょうか? そもそもなぜListでやろうと思った(Listでやる必要性は?)のでしょうか?まずListやSetの使い分けを学んだほうがいいと思います。 また、Collectionを仮に、実装するクラスを作ってみたのですが、 一般に、このような形で使われる亊はあったりするのでしょうか? 普通はCollectionを直接実装するようなことはしません。すでに用意されているもの(ArrayList、LinkedList、HashSet、TreeSet 、HashMap etc...)で間に合うからです。 また、 public class HeightComparator2 extends HeightCollection implements Comparator<Human2> という継承もおかしいです。CollectionとComparator両方を継承してしまっては、Strategyパターンの意味がない(というかStrategyパターンではない)です。Comparator(並べ替えるためのロジック)を入れ替えることによって、並べ替え方を変えることができるというのがポイントです。CollectionとComparator両方を混ぜてしまっては、あるひとつの方法でしか並べ替えることができない、柔軟性がないものになってしまいます。

kannitiha
質問者

補足

ありがとうございます。 それで、ソースを考える前にきいておきたいのですが、 SortedSet<Human> heightSortSet = new TreeSet<Human>(new HeightComparator()); の、heightSortSet , TreeSetをそれぞれクラスに変えて考えてみればいいのでしょうか? たとえば、仮に、 クラスをキーに、そこに属する生徒をとりだす場合と、そのクラスの教師をとりだす場合とでわけた時 それぞれのdb取得方法を別クラスに設定して、 new HeightComparator()のような役 SortedSet 、DBConnectionとかといった、dbにアクセスクラス といった考え方はできるのでしょうか? どうしても、ソースを上手く考えられません。 よろしくお願いします。

その他の回答 (6)

  • hoge_piyo
  • ベストアンサー率57% (15/26)
回答No.6

最初の質問と少しずれてきてしまいましたが・・・とりあえずStrategyパターンについて解説しておきます。 sampleだからしかたないですが、リンク先のページは単純にしすぎて逆にわかりづらいですね・・・MyClassが単純すぎてほとんど意味がありません。 以下にもう少し実際に近いsampleを載せます。Strategyのポイントは"アルゴリズムを入れ替える"ということです。 TreeSetのComparatorに違うものを使用することによって、体重別と身長別という異なる順でソートしています。この場合、最初からTreeSetはStrategyパターンで設計されています(途中でComparatorを入れ替えられないので、厳密にはStrategyパターンとは言えないかもしれませんが) このように、そもそもJavaのコレクション自体の多くのところでデザインパターンが使用されているので、ソースコードを読んでみるといいでしょう。 public class CompareTest { public static void main(String[] args) { Set<Human> people = new HashSet<Human>(); people.add(new Human("一郎",170,60)); people.add(new Human("二郎",165,55)); people.add(new Human("三郎",175,58)); people.add(new Human("四郎",160,67)); people.add(new Human("五郎",180,62)); SortedSet<Human> heightSortSet = new TreeSet<Human>(new HeightComparator()); SortedSet<Human> weightSortSet = new TreeSet<Human>(new WeightComparator()); heightSortSet.addAll(people); weightSortSet.addAll(people); System.out.println("身長順"); for(Human h:heightSortSet){ System.out.println(h); } System.out.println("\n体重順"); for(Human h:weightSortSet){ System.out.println(h); } } } class Human{ Human(String name,int height,int weight){ this.name = name; this.height = height; this.weight = weight; } public final String name; public final int height; public final int weight; @Override public String toString(){ return "名前:"+name+" 身長:"+height+" 体重:"+weight; } } //身長で比較するComparator class HeightComparator implements Comparator<Human>{ @Override public int compare(Human h1,Human h2) { return h1.height - h2.height; } } //体重で比較するComparator class WeightComparator implements Comparator<Human>{ @Override public int compare(Human h1,Human h2) { return h1.weight - h2.weight; } }

kannitiha
質問者

補足

解答ありがとうございます 調べてみました。 コレクションというのは、List,ArrayList, Set,HashSet etc...の亊を言うのでしょうか? また、 List<Human> heightList = new ArrayList<Human>(new HeightComparator()); の系式で表す亊はできるのでしょうか? このときのアルゴリズムをいれかえる動作というのは、 ソースでいうと、 SortedSet<Human> heightSortSet = new TreeSet<Human>(new HeightComparator()); SortedSet<Human> weightSortSet = new TreeSet<Human>(new WeightComparator()); の部分の亊をいうのでしょうか? 一方、これをListでも実現する亊はできるのでしょうか? その場合、Collectionを実装する必要があるように感じるのですが。。。 以下、一度考えてみました。 //HeightComparatorを変えたソース public class HeightComparator2 extends HeightCollection implements Comparator<Human2> { public int compare(Human2 h1,Human2 h2) { System.out.println("test--- during //// "); System.out.println("h1.height +"+h1.height + "/h2.height:" + h2.height); return h1.height - h2.height; } } //Collectionを実装したクラス public class HeightCollection implements Collection { } public class SampleRun{ public static void main(String[] args){ //Listに入れる型を指定しておく List<Human2> list = new ArrayList<Human2>(); list.add( new Human2("right", 120,24) ); //万一、Listにクラスインスタンスを入れようとしたら、Collectionでしか対応しない // List<Human2> heightList = new ArrayList <Human2>( (Collection) new HeightComparator2()); List<Human2> heightH = new ArrayList<Human2>(); heightH.addAll(list); heightH = new ArrayList<Human2>(); heightH.addAll(list); heightH = new ArrayList<Human2>(new HeightComparator2()); for(Human2 ha: heightH) { System.out.println("ha::: " + ha); } } } 補足: また、Collectionを仮に、実装するクラスを作ってみたのですが、 一般に、このような形で使われる亊はあったりするのでしょうか? よろしくお願いします。

  • hoge_piyo
  • ベストアンサー率57% (15/26)
回答No.5

補足についての回答 2については、やはりこのようにつかうなら、インスタンス変数はfinalにして、コンストラクタで設定するほうがいいでしょう。 setterを用意するということは、初期化に値を定めることができない、もしくは値を書き換える(内部の状態を変える)必要があるときです。nullチェックが必要になってしまいますし。 3については・・・ 多重継承が出来る言語なら、ある機能を他のクラスで定義して、継承することによって取り入れるという使い方は可能なのですが、Javaの場合だとちょっとまずいですね。プログラムが大きくなってきた場合、このような使いかたをしていると、逆にプログラムの構造を変更するのに、大変になる場合があります。 他の方もいっていますが、Javaの場合は特に、本当にis-a関係がある時だけ継承を使いましょう。 あと細かいとこですが、今のままだと切断の前にconがnullの可能性があるので、nullチェックしないといけません。 生徒は実際に存在するものなので、それをClassにするというのは結構思いつきやすいんですが、データベースの場合は、プログラムを作る人が、考えなければいけないので、難しいです。 私が前Javaでデータベース接続のクラスを作ったときは、Strategyパターンで作りました。DBの接続、データ取得の汎用的な処理をDB接続用のクラスにもたせて、具体的な取得方法など別に用意して、そのクラスに渡すというやりかたです。

kannitiha
質問者

補足

遅くなりました。 解答ありがとうございます。 strategyパターンについて調べてみました。 その際、 http://www.techscore.com/tech/DesignPattern/Strategy.html を参考にしたのですが、 この場合、ageとheightとweightそれぞれを比較するクラスを別クラスとして実装していますが これを実際に実行しようとしたら、 どう考えるべきなのでしょうか? 1)Humanクラスにデータを設定 2)Comparatorを実装するeightComparator,AgeComparator,WeightComparatorクラスに渡す この時のa),b)の宣言のちがい a)再利用性の意味がない = ComparatorをHeightComparatorに実装する時にメンテナンスの見通しがいる b)再利用性の意味あり = ComparatorをHeightComparatorに実装する時にメンテナンスの見通しがいらない また、b)とc)のちがいは、クラスとしてかメソッドとして取るか と考えられるのでしょうか? 使用クラス HeightComparator,AgeComparator,Human, SampleClass ーーーー SampleClass ------------- public class SampleClass { private Comparator comparator = null; public SampleClass(Comparator comparator){ this.comparator = comparator; } public int compare(Human h1,Human h2){ return comparator.compare(h1,h2); } } ーーーー 実行クラス --------------- public class SampleRun { public static void main(String[] args) { //Comparator cp = null ; SampleClass sc = new SampleClass(cp); Human hm = new Human("かりん",161,48,15); Human hm2 = new Human("ちぐさ",157,50,15); int mc = new AgeComparator().compare(hm, hm2); System.out.println("mc:"+mc); a) int mc2 = new HeightComparator().compare(hm,hm2); System.out.println("mc2:"+mc2); b) cp = new HeightComparator(); System.out.println("cp:" + cp.compare(hm, hm2) ); c) int mc3 = new HeightComparator().compare(hm, hm2); System.out.println("mc3.compare:"+mc3); } } 結果: h1.age:15/h2.age:15 mc:0 mc2:1 また、このページで「SampleClassは以下のように記述することができます」 とあるが、MyClassとなっている。 これはこれで正しいのでしょうか? よろしくお願いします。

  • public_sa
  • ベストアンサー率52% (13/25)
回答No.4

プログラムも 実世界の構造にあわせたほうが 汎用性の高いプログラムが出来るんでは ないか?と感じてます。 っていうかそういう場合がほとんどです。 1)の StudentがstudentNumberを持つ StudentがstudentNameを持つ これはHAS-Aとして成り立つと思います。 実世界でも生徒が名前や出席番号を持っています。ね。 2)の StudentFormBean#setStudentClassの 引数型が無いのでよくわかりません super.sutudentClassも見えないのよくわかりません 生徒データを管理するのは先生?っていうのをコード化し 質問の >>2)生徒は、クラスに属する = IS-Aで考えられないか。 をもう少し紐解くと 生徒は、クラスに属する の逆を言うと クラスは生徒達を持つになりませんか? 1クラスに付き生徒1人なんて事はまずないので。。。 っていう事は、 class クラス { private 生徒達 sutudents; } ってなりますね。 生徒データを管理するものが必要だとしたら 管理するオブジェクトが生徒を持つのが 妥当かと、 そこで生徒達クラスの登場となります。 生徒達クラスが複数の生徒を管理する手段を提供すればよいと思います。 class 生徒達 { pivate 生徒[] sutudents; //例えば以下のように使いやすくなります。 private int get生徒人数 { return this.sutudents.length;} private int get男子生徒人数{ //this.sutudensを調べ返す //何で男子人数が判るかは下の[class Student extends 人]でわかります } } もっと言うとクラスを担当するのは先生なので class 先生 { private クラス clazz; } ここまでで先生がクラスを担任し、クラスには生徒達が存在し、 クラス単位で生徒達を管理するっていう形が出来上がったと思います。 じゃぁいつIS-Aが成り立つのか思いました? 例えば生徒も先生も人ですね。 以下例えばですよ。 class Student extends 人 {} class 先生 extends 人 {} class 人 extends 生き物{ private 性別; pivate 年齢; } class 生き物{ private 命; } ってすれば 先生クラスを見れば先生は人なんですから性別も年齢も 判断できることが保障されますね。 人である以上生き物なんですから 命があることもコード上保障されますね。 先生をインスタンス化する時点で保障すべき 事にはIS-Aが成り立つ、 HAS-AではOBJECT_Aが持つOBJECT_Bへの アクセス手段をオブジェクトAが実装しない限り保障されませんよね。 そのフィールドをカプセル化するのはもちろん、 アクセス手段・インスタンス化手段も限定できる それがカプセル化。 IS-Aではそのオブジェクトがインスタンス化された時点で 親オブジェクトの機能は保障されることになります。 それが継承であり、それを抽象化・Interface化することが ポリモーフィズムってことかな。 カプセル化できてなければ多能性もなくなるし、 多能性が無ければオブジェクト指向でなくて 手続き型のプログラムでよいと思うし 全てある程度できて使えるプログラムかなっておもうよ。 で DBのAccessor・DBConnectorの話になると、 DBConnectorは接続先情報を持つ。 AccessorはDBConnectorを持つ っていう風にしたほうが汎用性が高くなんじゃないかな? 今のままだと StudentDBAccessor IS DBConnectorだから DBConnectorであるStudentDBAccessorしか拡張できない。 以下みたいな考えが理解できると 汎用性の多少あるプログラムが書けるかも。 class DBAccessor extends Accessor{ private DBConnector connector; } class StudentDBAccessor extends DBAccessor{ private QueryExecuter executer; } class DBConnector extends Connector{ private DataSource ds; } DataSource - 接続先情報 QueryExecuter - SQL実行クラス と理解してください。 長文すみません わからないことあったらまた聞いてください。

kannitiha
質問者

補足

解答ありがとうございます。 遅くなりました。 この時なのですが、 DBConnectorを共用化しようとした場合どうすべきなのでしょうか? private DBConnector connector; のように定義したら、毎回初期化される气がする。。。 一度サンプルに関して、考えてみました。 それで、 QueryDBAccessorクラスは、 public class QueryExecuter implements StudentInterface { private Connection con; //指定するクラスに属する生徒をとりだす public void getStudents(){ Statement stmt = null; try{ String sql = createSqlSelectStudents(); con.prepareStatement(sql); stmt.setDataSelectStudent(); ResultSet rs = stmt.executeQuery(); //dbから取りだした結果をよびだしクラスに返す while(rs.next()){ //?ここでとりだす? } }catch(Exception e){ } } protected abstract String createSqlSelectStudents(){ //sql文 return sql文.toString(); } protected abstract void setDataSelectStudent(){ } } public interface StudentInterface{ protected abstract String createSqlSelectStudents(); protected abstract void setSelectStudent(); } な感じでしょうか? また、 DBAccessor 色んなクラスからよばれる ex) 先生を新たに追加する、etc... DBConnector dbに接続する際の処理 全体に共通するもの StudentDBAccessorは、生徒に関わる処理 っていう感じでしょうか? できたら、処理のイメージ的なものを出してもらいたいのですが。。。 よろしくお願いします。

  • public_sa
  • ベストアンサー率52% (13/25)
回答No.3

IS-A, HAS-Aの考え方を持つと抽象化もしやすく オブジェクト思考が一歩進むと思います。 例えば 人は名前を持つ(HAS-A) 人は動物である(IS-A) これを抽象化して使いやすく 砕いていくと結構汎用性の高いオブジェクト指向でる プログラミングができると思います。 簡単に言うと IS-Aなら継承で表す HAS-Aならフィールドに保持する って言うような設計にすると 汎用性の高いプログラムになると思います。 以上を踏まえて 以下は、コードを見て直感的に書きますが。 今のサンプルコードの考え方だと StudentDBAccessor IS DBConnector になってるけど DBConnectorは接続先を持つ訳で、 StudentDBAccessor extends DBConnectorでは 接続先DBが増える都度クラスの増設・改修などが 増えてしまいそうと思いました。 とりあえず簡単に意見でした。 もし、もうすこし噛み砕いたほうが よいなら再度質問してください。

kannitiha
質問者

補足

回答ありがとうございます。 たとえば、 今の処理で、 1)生徒は、名前、学生Noをもつ = HAS-Aの考えかた 2)生徒は、クラスに属する = IS-Aで考えられないか。 のようにするとしたら、IS-Aを使用することはできるのでしょうか? その場合、イメージ的に 1) public class StudentFormBean{ private int studentNumber; //フィールドとしてもつ private String studentName; //フィールドとしてもつ } 2)生徒のクラスを管理する public class StudentClass{ public void setStudentClass(){ } //生徒のクラスデータのとりだし public StudentClassFormBean getStudentClass(){ } } 生徒のデータを管理する public class Student extends StudentClass{   public void setStudent(StudentFormBean sFr){       //クラスデータをとってきて、生徒データを追加    super.studentClass();   } } として考えるとまた違ってくるということなのでしょうか? > 接続先DBが増える都度クラスの増設・改修などが 増えて。。。 その場合どう変えるべきなのでしょうか? >もし、もうすこし噛み砕いたほうが。。 おねがいします。 よろしくおねがいします。

  • buriburi3
  • ベストアンサー率44% (353/792)
回答No.2

>・繼承 >・カプセル化 >・ポリモーフィズム これはオブジェクト指向プログラムを実現するための手段であって、これ自体がオブジェクト指向ではありません。 これらの機能を使ってもオブジェクト指向とは呼べないプログラムを作る事は可能です。 オブジェクト指向はデータとデータを操作するプログラムのセットを一つの独立した固まり(オブジェクト)として扱う思想です。 >指定するクラスの生徒の情報をとりだすようなソースをつくりたい。 機能を中心に考えるのではなくデータを中心にして、データとデータを操作する為の機能のかたまりで考えると良いです。

kannitiha
質問者

補足

>>指定するクラスの生徒の情報をとりだすようなソースをつくりたい。 >機能を中心に考えるのではなくデータを中心にして、データとデータを操作する為の機能のかたまりで考えると良いです。 たとえば 今の場合、簡単にまとめてみると。 ーーデータ -- 生徒は、名前、生徒Numberをフィールドとしてもつ 生徒は、クラスに属している 生徒クラスは、クラス名、クラスNumberをフィールドとしてもつ ーー機能ーー クラスは、生徒を管理するクラスと、生徒を管理するクラスがある。 1)生徒を新たに追加するには、クラスを指定 2)クラスNumberから、クラスを特定するため(結果をbooleanでとりだす)の処理がいる = StudentClassDAO 3)2でクラスがあれば、そのクラスに属する生徒を追加 =StudentDAO と考えてみる、ということでしょうか? よろしくお願いします。

  • hoge_piyo
  • ベストアンサー率57% (15/26)
回答No.1

・繼承 ・カプセル化 ・ポリモーフィズム を総称したのが、「オブジェクト」志向と理解しています。 というのは間違ってないですが、オブジェクト指向といっても詳細な機能は言語によって違うので、(たとえば継承がなくてもオブジェクト指向という場合もあるし、Javaは基本型はオブジェクトではなく、ポリモーフィズムができないなど・・・) Javaをやるなら、Java的にわかりやすい、スタンダードなコーディングスタイルかどうかを意識した方がいいと思います。 それで、コードを見た感想としたは、だいたいはいいと思います。気になった点としては、 1.getStudentListの戻り値の型がListになっていますが、ジェネリックを使いましょう。List<StudentFormBean>とするべきだと思います。また、Listということは順序づけられているということになりますが、どのように順序付けて返すつもりなのでしょうか?順序付ける必要がないなら、Set、あるいはCollection型で返すという選択肢もあります。 2.StudentFormBeanについてですが、studentNameはいつ設定するのでしょうか?(privateのインスタンス変数なのにコンストラクタもないし、setterもない)また、studentNumberは変更できるようになっていますが、変更する必要があるのでしょうか?もし変更する必要がないなら、getterもsetterもなくして、インスタンス変数はfinalにして、コンストラクタで設定するようにしましょう。どちらにしろStudentFormBeanのインスタンスを、インスタンス変数をすべて空で作成する場面はあまり無いと思うので、引数ありのコンストラクタは必要でしょう。 3.DBConnector→StudentDBAccessor→StudentDAOという継承関係になっていますが、このような継承関係にした意図というか意味がいまいち見えてきません。たとえばStudentDBAccessorは抽象クラスになっていて、抽象メソッドを定義していますが、子クラスにおいてどのような実装を期待してこのような定義をしたのでしょうか? また、DBConnectorから継承していますが、コンポジションや委譲という関係で作成するという方法もあります。コンポジションは聞いたことがありますか?DBConnectorの中身が省略されていて、役割がわからないので、今の設計がいいとも悪いとも言えませんが・・・

kannitiha
質問者

補足

解答ありがとうございます。 全て書ききれないので、一部分先に、書きます。 1 今は、studentNumberでソートする形で考えています sql文で、ascを使用したパターンです。 2 nameは、numberと同じタイミングで設定します。 =単に、生徒のデータをとる時に設定する UserDAOクラスのgetStudentListは、 public List getStudentList(){ UserFormBean uFr = new UserFormBean(); List studentList = new ArrayList(); //dbからデータとりだし ResultSet rs = super.stmt.executeQuery(); while(rs.next()){ int num = rs.getInt("num"); String name = rs.getString("name"); uFr.setStudentNumber(num); uFr.setStudentName(name); studentList.add(uFr); uFr = new UserFormBean(); } return studentList; } の処理を考えています。 3 理由としては、処理を分割する亊で再利用しやすくするため、と考えていたのですが。 DBConnectorの内容としては、 public class DBConnector { public static Connection con = null; protected PreparedStatement stmtDb = null; /** * データベースを開放する */ public void DbConnect() { System.out.println("connecto"); try{ Class.forName("org.postgresql.Driver"); this.con = DriverManager.getConnection("jdbc:postgresql:shopping","postgresql","test"); }catch(Exception e) { System.out.println("ms:"+e.getMessage()); System.out.println("error:"+ e.getStackTrace()); } } /** * db接続を実行する */ public final void Connect() { //db接続を確認 if(this.con == null) { this.DbConnect(); } } /** * dbを切断する */ public void dbClose() { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } です。 意図としては、一度、dbに接続すると何度もアクセスしないですむようにしています。 ヨロシクおねがいします。

関連するQ&A

  • Javaのプログラムについて至急教えてください!

    //Sub.java class Super{ public void A(){} } class Sub extends Super{ /* (1) */ } このプログラムの(1)に入るものを下から2つ選んで他のクラスのメインメソッドから呼び出すのですがどうやってもわかりません。わかる方教えてください! public void A(){} public String A(){ return "pool";} public int A(String str){return Integer.parseInt(st);} public int A(){return 3;} public Object A(){return new Object();}

    • ベストアンサー
    • Java
  • 抽象クラスとオブジェクトを格納する配列(java)

    独習java第4版でわからない所があります。 abstract class Widget { String color; abstract int getMass(); public String toString() { return getClass().getName() + ": " + color + ", " + getMass(); } } class WidgetA extends Widget { final static int MASS = 4; WidgetA(String color) { this.color = color; } int getMass() { return MASS; } } class WidgetB extends Widget { final static int MASS = 1; WidgetB(String color) { this.color = color; } int getMass() { return MASS; } } class WidgetC extends Widget { final static int MASS = 5; WidgetC(String color) { this.color = color; } int getMass() { return MASS; } } class WidgetD extends Widget { final static int MASS = 17; WidgetD(String color) { this.color = color; } int getMass() { return MASS; } } class WidgetTypes { static int NUMWIDGETS = 6; public static void main(String args[]) { // 部品を格納する領域を宣言して割り当てる Widget widgets[] = new Widget[NUMWIDGETS]; // 部品を作成する widgets[0] = new WidgetC("Red"); widgets[1] = new WidgetA("Green"); widgets[2] = new WidgetD("Yellow"); widgets[3] = new WidgetB("Magenta"); widgets[4] = new WidgetA("Black"); widgets[5] = new WidgetC("White"); // 部品を処理する int totalMass = 0; for(int i = 0; i < NUMWIDGETS; i++) { Widget w = widgets[i]; System.out.println(w); totalMass += w.getMass(); } // 総重量を表示する System.out.println("Total mass = " + totalMass); } } これはある問題の解答ですが、僕にはどうしても理解出来ない部分があります。 mainのforループ内で Widget w = widgets[i]; totalMass += w.getMass(); となっています。 この仕組がわかりません。 まず Widget w = widgets[i] でWidget型の変数wにWidget型のwidget[i]を代入しているのにw.getMass()がエラーにならない理由がわかりません。(Widgetクラスは抽象クラスなのにwがWidgetクラスのインスタンスになっている?) これは 抽象メソッド( abstract int getMass() ) があるためでしょうか? ちなみにWidgetクラスとそのサブクラスからこの抽象メソッドを削除したらコンパイルエラーが出ました。 ではなぜ抽象クラスの抽象メソッドから、そのサブクラスのメソッドまで範囲が伸びるのでしょうか? どういう仕組でしょうか? この質問を書きながら思ったのですが、どうも配列の仕組みや抽象クラス・メソッドの仕組み、「オブジェクト」と「インスタンス」の違いがよくわかってないようです。 多分問題の本質はそこにあると思うんです。 駄文で申し訳ないです。 よろしくお願いします。

    • ベストアンサー
    • Java
  • インタフェイス実装と抽象クラス継承を同時に使うには??

    私はjava初心者です、今練習問題で困っています。 1つのクラスに抽象クラスとインターフェイスを 実装することはできるのでしょうか? 例えば abstract class Car { private String gas; public void getGas(int gas) { this.gas = gas; } public abstract void enjin(); } interface Flying extends Pet { void show(); } 上のインタフェイスと抽象クラスを同時に下のクラスに継承、実装しよう とすると、どんな風にかけば良いのでしょうか class Zoon { public Zoon() { super(); } public void enjin() { System.out.println("どどどどど"); } public void show() { System.out.println("いいくるまだ"); } }

    • ベストアンサー
    • Java
  • 継承について質問させていただきます

    Java初心者です。 privateなフィールドは継承されない と書籍にありましたが、理解に苦しんでおります。 具体例で申しますと、下記コードの cat.setCount(3); です。 CatクラスにはAnimalクラスの変数countは継承されないと考え、 エラーとなることを想像していたのですが。。。 なぜエラーとならないのでしょうか? 宜しければ、解りやすくご説明していただければ幸いです。 どうかよろしくお願いいたします。 ---------------------------------------------- class Animal{ private int count; int getCount(){ return count; } void setCount(int c){ this.count = c; } } class Cat extends Animal{ } public class test{ public static void main(String[] args){ Cat cat = new Cat(); cat.setCount(3); // ここが理解できません System.out.println(cat.getCount()); // ここも同様 } } ----------------------------------------------

    • ベストアンサー
    • Java
  • javaの配列とクラス

    abstract class abstract_class{ } class subclassA extends abstract_class{ int num = 1; } class subclassB extends abstract_class{ int num = 2; } class subclassC extends abstract_class{ int num = 3; } class Main{ public static void main(String args[]){ int sum = 0; abstract_class var[] = new abstract_class[3]; var[0] = new subclassA(); var[1] = new subclassB(); var[2] = new subclassC(); for(int i=0;i<3;i++) sum += var[i].num; System.out.println(sum); } } これをコンパイルすると Main.java:23: シンボルを見つけられません。 シンボル: 変数 num 場所 : abstract_class の クラス for(int i=0;i<3;i++) sum += var[i].num; ^ エラー 1 個 というエラーが出るのはなぜでしょうか? var[i]はみなsubclassA,subclassB,subclassCが代入されているのに、numはabstract_classの変数となっています。 よくわかりません。 よろしくお願いします。

    • ベストアンサー
    • Java
  • 敬称について教えてください

    class parent{ protected final static int val=10; } class Child extends Parent{ private int val=100; public void method(String s){ System.out.println(++val)} } } class Test{ int val=10; public static void main(String args[]){ Parent c=new Child(); c.method("HELLO"); } } 初歩的な質問ですみません。教えて下さい。 上記プログラミングで、下から3行目のc.method・・・ を記入してもコンパイルエラーがおこらないのはなぜでしょうか? 今回newしているのはChildのオブジェクトです。 が、型はParentです。 Parentにはmethodはないし、 なぜこれが許されるのかがわかりません。 分かりやすくおしえてもらえませんか?

    • ベストアンサー
    • Java
  • インナークラスを含むオブジェクトのXMLEncoding

    インナークラスを含むオブジェクトをXMLエンコーダで直列化しようとすると、 デフォルトコンストラクタが無いといった内容の例外が発生して失敗します。 そのインナークラスをトップレベルにリファクタリングすると、それは全く問題なく 動作することを確認しています。 インナークラスを含めたままXMLエンコーダで直列化するには、特別な方法が 必要なのでしょうか?仕様上不可能? これらに関する情報が全く見つからなくて困っています。 ご存知の方がおられましたら、よろしくお願いします。 import java.beans.XMLEncoder; import java.io.BufferedOutputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; public class EncodingSample { public class InnerClass { public int getIntValue() { return intValue; } public void setIntValue(int intValue) { this.intValue = intValue; } public String getStringValue() { return stringValue; } public void setStringValue(String stringValue) { this.stringValue = stringValue; } public InnerClass() { } public InnerClass( int intValue, String stringValue ) { setIntValue( intValue ); setStringValue( stringValue ); } private int intValue; private String stringValue; } public void setData( int intValue, String stringValue ) { innerClass = new InnerClass( intValue, stringValue ); } public void encode( String file ) throws FileNotFoundException { XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(file))); encoder.writeObject(this); encoder.close(); } public InnerClass getInnerClass() { return innerClass; } public void setInnerClass(InnerClass innerClass) { this.innerClass = innerClass; } public static void main(String[] args) { EncodingSample sample = new EncodingSample(); sample.setData( 12, "TextString" ); try { sample.encode("SampleFile.xml"); } catch (FileNotFoundException e) { e.printStackTrace(); } } public EncodingSample() { } private InnerClass innerClass; }

  • コンパイルエラー(Threadオブジェクト化)

    Runnableを継承したNormalClassをThreadとしてオブジェクト化しようとしているのですが、コンパイルエラーが出現して困っています。どうすればいいでしょうか? 下記エラー参照 Main.java:1: NormalClass は abstract でなく、java.lang.Runnable 内の abstract メソッド run() をオーバーライドしません。 下記ソース class NormalClass implements Runnable{ } class Main extends Thread{ public static void main(String args[]){ test = new Thread(new NormalClass()); } }

    • ベストアンサー
    • Java
  • 整数値を任意のオブジェクトを格納できるスタッククラスに格納する方法

    class ObjStack { private Object[] mBuf; private int mSP; public ObjStack(int size) { mSP = 0; mBuf = new Object[size]; } public int getSize() { return mBuf.length; } public int getNum() { return mSP; } public boolean isFull() { return mSP == mBuf.length; } public boolean isEmpty() { return mSP == 0; } public void push(Object x) { if (!isFull()) { mBuf[mSP++] = x; } } public Object top() { Object obj = null; if (!isEmpty()) { obj = mBuf[mSP-1]; } return obj; } public Object pop() { Object obj = null; if (!isEmpty()) { obj = mBuf[--mSP]; } return obj; } } 上のプログラムは任意のオブジェクトを格納できるスタッククラスです。 int型の値はオブジェクトではないので、このObjyStackクラスに格納することができない。 整数値をこのObjStackクラスに格納する方法を教えて下さい。

    • ベストアンサー
    • Java
  • Javaについて教えてください!

    public class Number{ private final String noo; private int ct; public Number(String noo){this.noo = noo;} public String getName(){return noo;} public void increment(){ct++;} public int getCount(){return ct;} public void reset(){ct = 0;} } このクラスを複数スレッドで使うためには、reset()とgetName()とgetCount()をsyncronizedで宣言すれば可能ですか?

    • ベストアンサー
    • Java

専門家に質問してみよう