880 Views
March 10, 25
スライド概要
- 手続き型から新しいパラダイムへ
- Java の基本
- Java におけるオブジェクト指向
- オブジェクトによるエラー処理
- データ構造
- オブジェクト指向における問題解決
機械学習や音声認識に関する書籍を執筆しています。
プログラミング〈新〉作法 ~これからプログラムを書く人のために ~ 4. Java: オブジェクト指向 手続き型から新しいパラダイムへ Java の基本 Java におけるオブジェクト指向 オブジェクトによるエラー処理 データ構造 オブジェクト指向における問題解決 1
4.1 手続き型から新しいパラダイムへ 手続き型(C言語など)のアイディア 段階的詳細化 : 対象とする大きな問題を小さな関数に分割 構造化プログラミング : 順次実行・条件分岐・繰り返し データ構造と操作手続きが分離していることが問題 新しいプログラミングパラダイムへ オブジェクト指向 データ構造と操作手続きを一体化し,オブジェクトとして扱う 基本的な処理手順はオブジェクト間のメッセージのやり取り 関数型 不変なデータと副作用のない関数の組み合わせ 2
4.1 手続き型から新しいパラダイムへ オブジェクト指向 ⼿続き型 ライブラリ 段階的詳細化 クラス設計 Classname + field: type 関数 構造化プログラミング 条件分岐 順次実⾏ + method(type): type 副作⽤の排除 関数 関数 関数 (メソッド) パイプライン 問題 関数 継承‧委譲 関数型 関数 関数1 データ 繰り返し :Object dispatch return 関数3 データ 部品としての関数 基本操作 強⼒な パターンマッチ :Object 関数2 Map Filter データ (フィールド) Reduce データ構造 メッセージパッシング 3
4.2 Java の基本 の特徴 "Write Once, Run Anywhere" というスローガンに基づいた中間言語方式のオ ブジェクト指向型言語 さまざまなハードウェア用に用意された Java 仮想マシン JVM 上で実行可能 Java import java.util.*; public class App1 { public static void main(String[] args) { System.out.println("Enter your name"); } } .java ソースコード ファイル ライブラリ JVM JVM コンパイル バイトコード .classファイル JVM 4
4.2 Java の基本 言語仕様の概要 プログラムの単位はクラス クラス内の変数をフィールド,関数をメソッドとよぶ パッケージ ライブラリ pack1 java util Class1 .java App1 .java App2 .java クラス パッケージ名 package pack1 ライブラリの読み込み import java.util.*; クラス名 public class Class1 { フィールド名 Class1.java private int field1; private String field2; public void method1() { メソッド名 ... } public static void main(String[] args) { ... } ここから処理スタート フィールド定義 メソッド定義 main メソッド定義 5
4.2 Java の基本 入力・演算・出力を行う Java プログラムの例 import java.util.Scanner; public class Main { public static void main(String[] args) { var sc = new Scanner(System.in); int amount; final var price = 150; System.out.print("How many do you need?: "); amount = sc.nextInt(); System.out.println("Total: %d yen".formatted(price * amount)); sc.close(); } } How many do you need?: 5 Total: 750 yen 6
4.2 Java の基本 変数 宣言時に型を指定することが原則だが, var を用いることで型推論が可能 種類 型 値の例 整数 int, byte, short, long 512, -3 浮動小数点数 double, float 12.187, 3.45E-5 文字 char 'a', '\n' 論理値 boolean true, false 演算子 C言語とほぼ同じだが,ポインタを操作する演算子はない 7
4.2 Java の基本 配列 Java では複数のデータを扱うときは,一般にはコレクションフレームワーク を用いる 基本型を要素とするような簡潔なデータ構造には配列も利用される int[] score = {80, 65, 70, 93, 77}; System.out.println(score[2]); // 70 8
4.2 Java の基本 制御構造(C言語との違い)(1/2) if 文 の条件式は真偽値を返す式でなければならない 拡張 for の使用が可能 配列やコレクションの要素を順に取り出す int[] score = {80, 65, 70, 93, 77}; for (int s: score) { System.out.println(s); } 80 65 ... 9
4.2 Java の基本 制御構造(C言語との違い)(2/2) 柔軟な switch 文 整数・文字列・enum などの型を変数として,その値に応じて処理を分岐 switch を代入文の右辺に書くと,式として扱うことができる 変数 値 値 switch ( ) { case 1 -> case 2 -> ... default -> } 処理 処理 処理 10
4.3 Java におけるオブジェクト指向 オブジェクト指向の考え方 C言語の構造体とJavaのクラスの違い Javaのクラスはデータと操作をまとめたもの 可視性の指定によって,外部へは必要最小限の機能のみを提供できるの で,クラスを抽象化された部品として扱うことができる 継承によって親クラスからフィールドやメソッドを引き継ぐことで,新 しい機能の追加や変更が容易になる 11
4.3 Java におけるオブジェクト指向 クラス C言語の構造体とほぼ同様の情報を持つクラスを定義する場合 このコードでは,各フィールドの可視性が private であり,外部から直 接アクセスできないようになっていることに注意 public class Student { private String name; private int score; } 12
4.3 Java におけるオブジェクト指向 可視性 プログラマが明示的に変数へのアクセス可能性を指定することができる 可視性 アクセスの可能性 public どのクラスからでもアクセスできる protected 同じパッケージ内のクラス,またはそのクラスを継承したクラスからアクセスできる 指定なし 同じパッケージ内のクラスからのみアクセスできる private 同じクラス内からのみアクセスできる 13
4.3 Java におけるオブジェクト指向 コンストラクタ クラスのインスタンスを生成するときに呼び出される特別なメソッド クラス定義の内部にクラス名と同じ名前のメソッドとして定義 呼び出す側は var s1 = new Student("Masa", 70); のようにフィールドに 格納する値を引数として渡し,これを初期値としてインスタンスを作成する this は自分自身のインスタンスを指す public Student(String name, int score) { this.name = name; this.score = score; } 14
4.3 Java におけるオブジェクト指向 アクセッサ 値を読み出す getter メソッドと,値を書き込む setter メソッドを可視性 public でクラス内部に定義したもの 変更される値の妥当性をチェックする処理を setter メソッドに組み込むな ど,通常の値の読み書きを超えた処理を行うことができる フィールドに対するアクセッサ // name public String getName() { return name; } public void setName(String name) { this.name = name; } 15
4.3 Java
におけるオブジェクト指向
プログラマが作成するメソッド
可視性の情報,返却値の型,メソッド名,仮引数宣言並び,メソッド本体の
ブロックの順に記述する
public void printData() {
System.out.println("Name: " + name + ", Score: " + score);
}
プログラムは main メソッドから開始される
public static void main(String[] args) {
var s1 = new Student("Masa", 70);
s1.printData();
}
16
4.3 Java におけるオブジェクト指向 継承されたメソッド 親クラスのメソッドは,子クラスでそのまま,またはオーバーライドして利 用できる 親クラスを明示していない場合でも,すべてのクラスは java.lang.Object クラ スを継承している java.lang.Object クラスの主なメソッド toString() : オブジェクトの文字列表現を返す equals() : オブジェクトの等価性を判定する hashCode() : オブジェクトのハッシュコードを返す 17
4.3 Java レコード におけるオブジェクト指向 のクラスとして,C言語の構造体に近い機能を持つもの イミュータブルなフィールドのみを持ち,コンストラクタや getter メソッド に相当する機能が自動的に生成される Java public record StudentRec(String name, int score) {} var s1 = new StudentRec("Masa", 70); System.out.println(s1.name()); // Masa System.out.println(s1.score()); // 70 18
4.3 Java におけるオブジェクト指向 オブジェクトの仕組み コンストラクタとクラスメンバ コンストラクタ : クラスからインスタンスを作成するときに呼び出される メソッド.シグニチャの異なる複数のコンストラクタを定義できる クラスメンバ : クラス内で共有されるフィールドやメソッド スタティックメンバ : インスタンス化が不要で,クラス名から直接ア クセスできる インスタンスメンバ : インスタンスを通じてアクセスできる 19
4.3 Java におけるオブジェクト指向 コンストラクタとクラスメンバ クラス定義 public class Student { private String name; private int score; public Student( ... ) { this.name = name; this.score = score; } コンストラクタ フィールド メソッド public String getName() { return name; } クラスメンバ スタティックメンバ static修飾⼦が付くもの 実⾏開始前に⽣成 インスタンスメンバ インスタンス作成時に ⽣成 public void setName(String name) { this.name = name; } ... } 20
4.3 Java におけるオブジェクト指向 参照 インスタンスを格納した変数には,その参照が格納される var s1 = new Student("Masa", 70); 変数 s1 はこの宣言を含むメソッドのスタック領域に保持される インスタンス自体はヒープ領域に作成され,そのアドレスが変数 s1 の値と なる 21
4.3 Java におけるオブジェクト指向 参照をコピーしたときの振る舞い s1 s1 name: "Masa" score: 70 var s1 = new Student("Masa", 70); s2 s1 s2 name: "Masa" score: 70 name: "Masa" score: 70 75 var s2 = s1; s2.setScore(75); 22
4.3 Java におけるオブジェクト指向 継承と委譲 継承 : 親クラスのフィールドやメソッドを子クラスで利用する extends キーワードを用いて親クラスを指定 委譲 : 他のクラスのメソッドを利用する 集約 : 他のクラスのインスタンスを変数値として持ち,そのインスタンス のメソッドを呼び出すこと コンポジション : 他のクラスを部品として複雑なクラスを組み立てるこ と 23
4.3 Java
におけるオブジェクト指向
継承のクラス図とコード例
Queue
- data:ArrayList<Integer>
+enqueue(no: Integer) : void
+dequeue() : Integer
PriorityQueue
+priorityEnqueue(no: Integer) : void
public class Queue {
...
public void enqueue(Integer no) {
....
}
public Integer dequeue() {
....
}
}
public class PriorityQueue extends Queue {
public void priorityEnqueue(Integer no) {
....
}
}
24
4.3 Java におけるオブジェクト指向 節 参照] オブジェクト指向の設計図で,複数のダイアグラムによってプログラムを設 計するもの クラス図 各クラスはクラス名,フィールド,メソッドで構成される クラス間の関係 UML (Unified Modeling Language) [4.6.1 継承 実装 集約 コンポジション 25
4.3 Java におけるオブジェクト指向 抽象クラスとインタフェース 抽象クラス : 抽象メソッドが定義され,継承するクラスでメソッドの具体的 な処理を記述するもの インタフェース : メソッドの宣言のみが記述され,実装は継承するクラスで 行うもの インタフェースは複数実装できるが,抽象クラスは単一継承のみ インタフェースはフィールドを持つことができない 26
4.3 Java
におけるオブジェクト指向
インタフェースのクラス図とコード例
public interface Outer {
void algo(int no);
}
<<interface>>
Outer
+algo(no: int)
public class Fast implements Outer {
@Override
public void algo(int no) { ... }
}
Fast
Slow
+algo(no: int)
+algo(no: int)
public class Slow implements Outer {
@Override
public void algo(int no) { ... }
}
27
4.3 Java
におけるオブジェクト指向
ラムダ式
「 引数 -> 式 」という形式で記述される無名関数
関数型インタフェース : 1つの抽象メソッドを持つインタフェース
そのメソッドの実装部分をラムダ式で記述する
@FunctionalInterface
interface Calculator {
double calc(double a, double b);
}
28
4.3 Java
におけるオブジェクト指向
関数型インタフェースを用いてラムダ式で処理を差し替える例
public class Main {
public static void main(String[] args) {
//
Calculator add = (a, b) -> a + b;
System.out.println("10 + 5 = " + add.calc(10, 5));
加算
減算
//
Calculator subtract = (a, b) -> a - b;
System.out.println("10 - 5 = " + subtract.calc(10, 5));
...
}
}
29
4.4 オブジェクトによるエラー処理 オブジェクト指向におけるイベント イベントをオブジェクトとして扱える イベントの例 : エラーの発生・外部機器からの割り込み・GUI でのユー ザ操作など イベントを処理するコードをハンドラとよぶ エラー処理におけるイベントとハンドラ Java ではエラーが発生すると,そのエラーの種類に応じたイベントを処理系 に投げる 投げられたイベントはハンドラで処理する 30
4.4 オブジェクトによるエラー処理 Java のエラーイベントのクラス階層 Throwable +getMessage() : String さまざまなチェック例外 +printStackTrace() : void Error Exception さまざまな⾮チェック例外 RuntimeException 31
4.4 オブジェクトによるエラー処理 エラーを表すイベント エラーの 種類 システム エラー チェック 例外 非チェッ ク例外 クラス 説明 ランタイムでのトラブルが中心.エラーからの回復は実質 Error 的に不可能 エラーの発生が予測できて,回復可能なもの.例外処理の Excption 指定が必須 適切なコードを書くことによって大半は発生を回避できる RuntimeException エラー.例外処理の記述は任意 32
4.4 オブジェクトによるエラー処理 エラーの処理 33
4.4 オブジェクトによるエラー処理 非チェック例外 型の不整合やゼロ除算など,プログラムの実行中に発生する可能性があるエ ラー RuntimeException クラスを継承したクラスのインスタンスが投げられる プログラマが対処の必要性の有無を判断することができる try-catch で例外処理を行うプログラム例 Listing 4-5 34
4.4 オブジェクトによるエラー処理 チェック例外 ファイルの読み書きやネットワーク通信など,外部リソースにアクセスする 際に発生する可能性があるエラー Exception クラスを継承したクラスのインスタンスが投げられる プログラマが例外処理を記述しないとコンパイルエラーとなる ファイル入出力を行うプログラム例 Listing 4-6 35
4.5 データ構造 コレクションフレームワーク データサイズを実行時に自由に変更できるデータ構造 用途に応じたリスト・セット・マップなどのインタフェースがある Collection List ArrayList Set LinkedList HashSet Map TreeSet HashMap TreeMap 36
4.5 データ構造 ジェネリックスと型パラメータ ジェネリックス : 型をパラメータとしてクラスやメソッドを定義する機能 型パラメータ : クラスやメソッドの宣言時に指定する型のこと 例 : 文字列を要素とするリストの宣言 List<String> namelist = new ArrayList<>(); 37
4.5 データ構造 要素へのアクセス リストへのアクセス方法 : アレイとリンクドリスト アレイ : 配列を用いて実装されたリスト リンクドリスト : リストの要素が次の要素への参照を持つ セット・マップへのアクセス方法 : ハッシュとツリー ハッシュ : キーをハッシュ関数で変換し,その値をインデックスとして 要素にアクセス ツリー : 二分木などのデータ構造を用いて要素を格納 38
4.5 データ構造 リストへのアクセス ArrayList Listing 4.7 内部的に配列を用いているので,インデックスを使った要素へのアクセ スは高速だが,要素の追加・削除には要素の移動が伴うため遅くなる LinkedList 内部的に連結リストを用いているので,要素の追加・削除は高速だが, インデックスを使った要素へのアクセスは遅くなる ArrayList LinkedList 39
4.5 データ構造 ハッシュ バケットとよばれる予め決められたサイズの配列を用意する データ格納時には,ハッシュ関数用いて格納するバケット決める データ検索時には,ハッシュ関数を用いてバケットを特定する インデックス バケット "Alice" ハッシュ関数 hashCode() 0 63350368 1 2 equals() 68 "Alice" LinkedList 40
4.5 データ構造 ツリー ツリーは,データを保持する節・葉と,それらを結ぶ枝からなるデータ構造 二分木は,各ノードが最大2つの子ノードを持つ木構造で,各ノードの左の子 ノードの値はそのノードの値より小さく,右の子ノードの値はそのノードの 値より大きいという性質を持つ 1003 "Caroline" 1002 1005 "Bob" "Eve" 1001 1004 1007 "Alice" "David" "Giant" 41
4.5 データ構造 メモリ管理 Java では,メモリ管理は JVM が行う ガベージコレクタは,参照されていないオブジェクトを探し,解放する ヒープ領域 ガベージコレクション 使⽤中のメモリ 使⽤済みのメモリ 空きメモリ 42
4.5 データ構造 データベース プログラムの外部でデータを管理するための仕組み データが大量にある場合や,データが複数のプログラムからアクセスされて 頻繁に書き換えられるような場合に有効 データベースの種類 リレーショナルデータベース NoSQL データベース 43
4.5 データ構造 リレーショナルデータベース データを表形式のテーブルで保存し,テーブルはキーを用いて結合 操作言語は SQL 顧客テーブル 商品テーブル 顧客id ⽒名 住所 商品id 商品名 単価 ... ... ... ... ... ... P01 ... ... ... ... ... ... C01 C02 C03 ⽇付 P02 P03 販売管理テーブル 顧客id 商品id 個数 2024/01/08 C03 P02 100 2024/01/10 C01 P02 200 2024/01/10 C01 P01 50 2024/01/31 C03 P02 150 44
4.5
データ構造
データベース
扱うデータが表形式に合わない場合や,特定のアプリケーションで高速なデ
ータアクセスが求められる場合などに使われる
NoSQL
{
"name": "Takao",
"address": {
"city": "Kyoto",
"zipcode": "600-1111"
},
"hobbies": ["sleep", "eat"]
collection
Mongo
DB
documents
(a) MongoDB
}
db.users
.find("hobbies": "eat")
:FRIEND
Bob
:FRIEND
Alice
Fin
since:2020
MATCH (a {name:"Alice"})
-[:FRIEND]
-(b)
-[f:FRIEND]
-(c)
WHERE f.since >=2020
RETURN c
(b) Neo4j
45
4.6 オブジェクト指向における問題解決 オブジェクト指向の典型的な問題解決の手順 i. 問題解決に必要なオブジェクトを洗い出し,クラスを設計する ii. 全体の処理手順を明確にし,状態管理を行うクラスの振る舞いを定義する iii. オブジェクト間のメッセージの交換手順を記述する これらの手順を支援する道具 UML : オブジェクト指向の設計図 デザインパターン : 頻出問題に対する解決策のパターン 46
4.6 オブジェクト指向における問題解決 UML オブジェクト指向プログラミングの設計を図式化するための言語 クラス図 OrderManager +processOrder() classDiagram class OrderManager { +processOrder() +cancelOrder() +shipOrder() } class Book { -title: string -author: string -price: float +getTitle() +getAuthor() +getPrice() } OrderManager "1" o-- "*" Book : contains +cancelOrder() +shipOrder() 1 contains * Book -title: string -author: string -price: float +getTitle() +getAuthor() +getPrice() Mermaid UML 47
4.6 オブジェクト指向における問題解決 状態遷移図 オブジェクトの取りうる状態および状態間の遷移条件を表現 NewOrder stateDiagram-v2 Order Received [*] --> NewOrder NewOrder --> Processing: Order Received Processing Processing --> Shipped: Order Shipped Processing --> Cancelled: Order Cancelled Shipped --> [*] Order Shipped Order Cancelled Cancelled --> [*] Shipped Mermaid Cancelled UML 48
4.6 オブジェクト指向における問題解決 シーケンス図 オブジェクト間のメッセージのやりとりを時系列で表現 sequenceDiagram actor Customer Manager Book Payment Customer Place Order participant M as Manager participant B as Book Select Book participant P as Payment Book Info Process Payment Customer->>M: Place Order M->>B: Select Book Payment Confirmation B-->>M: Book Info Order Confirmation M->>P: Process Payment P-->>M: Payment Confirmation Ship Book M->>Customer: Order Confirmation M->>Customer: Ship Book Mermaid Manager Book Payment Customer UML 49
4.6 オブジェクト指向における問題解決 デザインパターン 1994年に Erich Gamma ら4人によってまとめられた 新しいプログラミング言語では,言語仕様の一部として組み込まれているこ とが多い 50
4.6
オブジェクト指向における問題解決
イテレータパターン
要素の並びからなるオブジェクトに対して,要素を順に取り出す方法
次の要素の有無を論理値型で返す hasNext() メソッドと,次の要素を返す
next() メソッドを持つ
import java.util.Iterator;
...
boolean found = false;
Iterator<String> it = namelist.iterator();
while (it.hasNext()) {
if (it.next().equals(searchName)) {
System.out.println("Found " + searchName);
found = true;
break;
}
}
51
4.6 オブジェクト指向における問題解決 デコレータパターン デコレータオブジェクトが他のオブジェクトをラップして,オブジェクトに 対して機能を追加する このコードは古い書き方です // BufferedReader br = new BufferedReader(new FileReader("data.csv")); 52
4.6
オブジェクト指向における問題解決
ストラテジーパターン
アルゴリズムを実行時に交換する
import java.util.List;
import java.util.ArrayList;
import java.util.Comparator;
public class Main {
public static void main(String[] args) {
List<String> namelist = new ArrayList<>(
List.of("David", "Alice", "Caroline", "Bob", "Eve"));
namelist.sort(Comparator.naturalOrder());
for (String person: namelist) {
System.out.println(person);
}
}
}
53
4.7 まとめ オブジェクト指向の考え方: 手続き型からの発展 Javaの基本: クラス,フィールド,メソッド,コンストラクタ,アクセッサ,継 承,インタフェースなどの概念 イベントとハンドラ: エラー処理の仕組み データ構造: コレクションフレームワーク(List, Set, Map)と,それらを活用した データ構造の実装方法 オブジェクト指向における問題解決: UMLによる図式化や,デザインパターンの活 用方法 54