プログラミング講義 Chapter 10: オブジェクト指向プログラミング (Object-Oriented Programming=OOP) の入り口の入り口の入り口 秋山英三 F1027 1 例 : 部屋のデータを扱う // Test.java の内容 public class Test { public static void main(string[] args) { double length1, length2, length3, width1, width2, width3, height1, height2, height3; length1 = 10.0; // 秋山の部屋の長さ width1 = 8.0; // 秋山の部屋の幅 height1 = 2.5; // 秋山の部屋の高さ length2 = 3.0; // 小人の部屋の長さ width2 = 2.0; // 小人の部屋の幅 height2 = 1.0; // 小人の部屋の高さ length3 = 20.0; // 曙の部屋の長さ width3 = 14.0; // 曙の部屋の幅 height3 = 4.0; // 曙の部屋の高さ System.out.println(" 秋山の部屋の長さは " + length1 + " 幅は " + width1 + " 高さは " + height1 + " です "); System.out.println(" 小人の部屋の長さは " + length2 + " 幅は " + width2 + " 高さは " + height2 + " です "); System.out.println(" 出力 : 曙の部屋の長さは " + length3 秋山の部屋の長さは + " 幅は " + width3 10.0 + 幅は " 高さは 8.0 " 高さは + height3 2.5です + " です "); 小人の部屋の長さは 3.0 幅は 2.0 高さは 1.0です 曙の部屋の長さは 20.0 幅は 14.0 高さは 4.0です 2 1
問題点 length1 = 10.0; // 秋山の部屋の長さ width1 = 8.0; // 秋山の部屋の幅 height1 = 2.5; // 秋山の部屋の高さ length2 = 3.0; // 小人の部屋の長さ width2 = 2.0; // 小人の部屋の幅 height2 = 1.0; // 小人の部屋の高さ length3 = 20.0; // 曙の部屋の長さ width3 = 14.0; // 曙の部屋の幅 height3 = 4.0; // 曙の部屋の高さ あくまでも 9 つの独立した double の変数があるのみ length1 秋山の部屋 の 長さ という構造は プログラムをした人の頭の中にしかない 部屋 という概念があまり反映されてない 3 こういう書き方ができると直感的 room1.length = 10.0; // 部屋 1の長さ room1.width = 8.0; // 部屋 1の幅 room1.height = 2.5; // 部屋 1の高さ room2.owner = 小人 ; // 部屋 2のオーナーは小人 room2.length = 3.0; // 部屋 2の長さ room2.width = 2.0; // 部屋 2の幅 room2.height = 1.0; // 部屋 2の高さ room3.owner = 曙 ; // 部屋 3のオーナーは曙 room3.length = 20.0; // 部屋 3の長さ room3.width = 14.0; // 部屋 3の幅 room3.height = 4.0; // 部屋 3の高さ ピリオドで階層化 部屋ごとに情報をまとめる 部屋 という モノ 対象 が明確になる (1) 部屋 と その (2) 持ち主 長さ 幅 高さ との2つのレベルを分けることができる 4 2
モノ ( 対象 ) の属性 (property) データ 情報 room1.length = 10.0; // 部屋 1の長さ room1.width = 8.0; // 部屋 1の幅 room1.height = 2.5; // 部屋 1の高さ length, width, height などが 部屋の 属性 データ 情報 だとハッキリ分かる room1.height room1 の 高さ (height) 直感的に分かりやすい表記方法 各 部屋 の情報を それぞれ一カ所にまとめることができる! 5 こういう書き方をするには準備が必要 room1.length = 10.0; // 部屋 1の長さ room1.width = 8.0; // 部屋 1の幅 room1.height = 2.5; // 部屋 1の高さ クラス を使う 6 3
クラスを使う方法 [ ステップ 1] 別ファイルで クラス を定義する ( 本当は同じファイルでも良いがとりあえず ) クラスの フィールド を定義する フィールド = 高さ 長さなどの 属性 を保持するデータフィールド // Room.java に Roomクラス を定義する String owner; // 持ち主の名前 double length; // 長さ double width; // 幅 double height; // 高さ // 別ファイル public class クラス名 { 型フィールド名 ; 型フィールド名 ; 型フィールド名 ; 型フィールド名 ; 7 クラスを使う方法 [ ステップ 2] クラスのインスタンス (instance) を作る 配列 の時と同様の手続き ( 参照型 ) 1. 変数の宣言 2. インスタンス作成 ( 記憶領域を確保 ) ( ) に注意 // Test.java の先頭部分 public class Test { public static void main(string[] args) { Room room1; // (1) 変数の宣言 room1 = new Room(); // (2) インスタンスの作成 Room room2 = new Room(); // 宣言とインスタンス作成を Room room3 = new Room(); // 同時にやっても良い 8 4
[ ステップ 3] あとは普通の変数と同様に使うことが出来る // Test.java : 変数の宣言 インスタンス作成のあと room1.length = 10.0; // 部屋 1の長さ room1.width = 8.0; // 部屋 1の幅 room1.height = 2.5; // 部屋 1の高さ System.out.println(room1.owner + " の部屋の幅は " + room1.width + " です "); 出力 : 秋山の部屋の幅は 8.0 です 9 [ 注意 ] コンパイルのやり方 Room.java で定義した Room クラス を Test.java で使うとき Test.java (main() メソッドがあるソースファイル ) をコンパイルする java Test で実行 => javac Test.java => java Test 10 5
クラスを使う方法 : まとめ Room.java // Roomクラス を定義 String owner; // 持ち主の名前 double length; // 長さ double width; // 幅 double height; // 高さ => javac Test.java => java Test // Room クラスを使う public class Test { public static void main(string[] args) { // 変数の宣言とインスタンスの作成 Room room1 = new Room(); // フィールド変数の値を設定 room1.length = 10.0; // 部屋 1の長さ room1.width = 8.0; // 部屋 1の幅 room1.height = 2.5; // 部屋 1の高さ Test.java // フィールド変数を使う System.out.println(room1.owner + " の部屋の幅は " + room1.width + " です "); 11 クラスとインスタンス クラス 部屋 目覚まし時計人間円三角形 インスタンス ( 実例 ) 私の部屋 あなたの部屋 高木さんの部屋 私の目覚まし時計 あなたの 秋山 小泉 森 半径 1.5の円 半径 0.8の円 三辺 3,4,5cmの三角形 三辺 5,12,13cmの三角形 それぞれクラスの属性フィールドは何? 12 6
クラスと メソッド method = 手順 方法クラスに メソッド を定義する // Room.java に クラス を定義する String owner; // 持ち主の名前 double length; // 長さ double width; // 幅 double height; // 高さ // 部屋の体積を計算する double getvolume () { return length * width * height; // 部屋の表面積を計算する double getsurfacearea () { return (length * width + length * height + width * height) * 2; public class クラス名 { 型フィールド名 ; 型フィールド名 ; 型メソッド名 ( 引数列 ) { 型メソッド名 ( 引数列 ) { 13 インスタンスの メソッド を使う ( インスタンスメソッド ) // Test.java の途中から room1.length = 10.0; // 秋山の部屋 1の長さ room1.width = 8.0; // 秋山の部屋 1の幅 room1.height = 2.5; // 秋山の部屋 1の高さ System.out.println(room1.owner + " の部屋の体積は " + room1.getvolume() + " です "); System.out.println(room1.owner + " の部屋の表面積は " + room1.getsurfacearea() + " です "); < 実行結果 > 秋山の部屋の体積は 200.0 です 秋山の部屋の表面積は 250.0 です インスタンス変数. メソッド名 () で呼び出す 14 7
オブジェクト指向の入門の入門 ( 大事な性質が他にいっぱいある ) オブジェクト 1. フィールド ( 属性 状態 ) 2. メソッド ( 操作 手続き ) 人間 1. 属性 状態 ( 名前 髪の毛の色 栄養状態 身長 体重 ) 2. 操作 手続き ( 食べる 髪を染める ) 目覚まし時計 1. 属性 状態 ( 現在時刻 起床時刻 アラームOn/Off) 2. 操作 手続き ( 起床時刻を設定する アラームOn/Offを切り替える ) Windowsの画面の構成要素 Office 製品 15 願望 : インスタンス生成と同時に フィールド変数の初期値を設定 ( 初期化 ) してしまう ことはできないか? // Room クラスを使う public class Test { public static void main(string[] args) { // 変数の宣言とインスタンスの作成 Room room1 = new Room(); Test.java // フィールド変数の値を設定 room1.length = 10.0; // 部屋 1の長さ room1.width = 8.0; // 部屋 1の幅 room1.height = 2.5; // 部屋 1の高さ めんどう // フィールド変数を使う System.out.println(room1.owner + " の部屋の幅は " + room1.width + " です "); 16 8
たとえばこのように // Roomクラスを使う public class Test { Test.java public static void main(string[] args) { // 変数の宣言とインスタンスの作成と初期化 Room room1 = new Room( 秋山, 10.0, 8.0, 2.5); // フィールド変数を使う System.out.println(room1.owner + " の部屋の幅は " + room1.width + " です "); インスタンスト生成時に初期化を行う方法 答え コンストラクタ (Constructor) という特別なメソッ ドを設定すれば良い 17 コンストラクタ を用意すれば OK 特別なインスタンスメソッド ( 重要!) Room.java room1 = new Room( 秋山, 10.0, 8.0, 2.5); // Room.java に クラス を定義する String owner; // 持ち主の名前 double length; // 長さ double width; // 幅 double height; // 高さ // コンストラクタ public Room(String owner, double length, double width, double height) { this.owner = owner; this.length = length; this.width = width; this.height = height; クラス名と同じメソッド名にする 戻り値の型を書かない (void 型でもない ) 18 9
補足 : this インスタンス自身を指す Room.java // Room.java に クラス を定義する String owner; // 持ち主の名前 double length; // 長さ double width; // 幅 double height; // 高さ // コンストラクタ public Room(String owner, double length, double width, double height) { this.owner = owner; this.length = length; this.width = width; this.height = height; room1 = new Room( 秋山, 10.0, 8.0, 2.5); もちろん 引数の変数名 を フィールド名 と違うものにしておけば this はなくても大丈夫 owner, length, width, height は (1) コンストラクタの引数 (2) フィールド変数 の両方で使われている (2) を (1) から区別するのが this 黒板で説明 19 コンストラクタを使った初期化の例 // Roomクラスを使う Test.java public class Test { public static void main(string[] args) { // 配列変数の宣言とインスタンスの作成と初期化 Room[] rooms = { new Room("Alice", 5.0, 10.0, 3.0), new Room("Bob", 3.0, 4.0, 2.0), new Room("Carl", 4.0, 10.0, 6.0), new Room("Dave", 2.5, 6.0, 3.0), new Room("Alice", 4.0, 7.0, 4.0), ; // 全ての部屋の体積を表示 for (int i = 0; i < rooms.length; i++) { System.out.println( rooms[i].owner + " の部屋の体積は " + rooms[i].getvolume() ); 出力 : Alice の部屋の体積は 150.0 Bob の部屋の体積は 24.0 Carl の部屋の体積は 240.0 Dave の部屋の体積は 45.0 Alice の部屋の体積は 112.0 20 10
tostring メソッド tostring という名前のメソッド ( 凄く重要 というわけでもないが知っておくこと ) // Room.java に Room クラス を定義する フィールドの宣言 コンストラクタ public String tostring() { Room.java return owner + " の部屋 : 長さ =" + length + ", 幅 =" + width + ", 高さ " + height; // Roomクラスを使う Test.java (1) for (int i = 0; i < rooms.length; i++) { System.out.println( rooms[i].tostring() ); // Roomクラスを使う Test.java (2) for (int i = 0; i < rooms.length; i++) { System.out.println( rooms[i] ); 出力 : Alice の部屋 : 長さ =5.0, 幅 =10.0, 高さ 3.0 Bob の部屋 : 長さ =3.0, 幅 =4.0, 高さ 2.0 Carl の部屋 : 長さ =4.0, 幅 =10.0, 高さ 6.0 Dave の部屋 : 長さ =2.5, 幅 =6.0, 高さ 3.0 Alice の部屋 : 長さ =4.0, 幅 =7.0, 高さ 4.0 (2) は (1) と同じ出力 21 tostring メソッド 標準文字列 を出力する // Room.java に Room クラス を定義する フィールドの宣言 コンストラクタ public String tostring() { Room.java return owner + " の部屋 : 長さ =" + length + ", 幅 =" + width + ", 高さ " + height; // Roomクラスを使う Test.java (2) 出力 : Aliceの部屋 : 長さ =5.0, 幅 =10.0, 高さ3.0 Bobの部屋 : 長さ =3.0, 幅 =4.0, 高さ2.0 for (int i = 0; i < rooms.length; i++) { Carlの部屋 : 長さ =4.0, 幅 =10.0, 高さ6.0 System.out.println( rooms[i] ); Daveの部屋 : 長さ =2.5, 幅 =6.0, 高さ3.0 Aliceの部屋 : 長さ =4.0, 幅 =7.0, 高さ4.0 詳細は p.245-247 22 11
その他 クラス (static) メソッド については p.198, p.254 を参考に 例えば Java の Math クラスは 多くのクラスメソッドを持っている ( http://java.sun.com/j2se/1.4/ja/docs/ja/api/java/lang/math.html ) 23 12