【オブジェクト指向:後編】Javaで実際のコード解説 オブジェクト指向コーディング

当サイトは広告を含みます

今回はオブジェクト指向をJavaのコーディングで説明します。

概念の理解→具体的なコーディング作業にて理解が深まれば幸いです。

当記事のメインはオブジェクト指向です。
Javaのコーディングの仕組みや詳細についてはまた別記事にてご説明します。

こちらの記事概要
・初心者向け
・オブジェクト指向について
・概念をJavaコードで説明

オブジェクト指向の概要をよく知りたい方は下記をどうぞ。

目次

オブジェクト指向のおさらい

前編でご紹介したオブジェクト指向オブジェクトオブジェクト指向の基本機能についてもう一度おさらいを置いておきます。

オブジェクト指向について

オブジェクト指向とは、現実にあるモノ・事柄をシステムに落とし込むための概念を指します。

オブジェクトについて

オブジェクトとは『クラス』や『メソッド』といったデータや処理の集まりです。

代表的なオブジェクトとして下記があります。

オブジェクトに関わる機能

オブジェクトに密接にかかわる機能の1部です。

オブジェクト指向の機能

大きく分けて下記の3種類が挙げられます。

オブジェクト指向のメリット・デメリット

メリット

・システム開発目的の明確化
・保守性と再利用性が高い
・新機能追加などの拡張性がある

デメリット

・学習コストが高い
・他のプログラミングと比較して処理時間が長い
・過度な抽象化による冗長化

基本のコード: オブジェクトについて

例としてJavaで電卓システムのクラス『電卓システムのメインクラス』・『四則演算クラス』を見てみましょう。

Javaの場合、最初に読み込むクラス『メインクラス』が存在します。
メインクラスの中にはメインメソッドが存在し、プログラムが起動したら一番最初にメインメソッドが呼ばれます

メインメソッド1つのシステムに1つです。

/**
 * 01. 電卓システムのメインクラス
 */
public class MainCalculatorClass {

	/**
	 * 02. メインメソッド (1番最初に読み込まれるメソッド)
	 * @param args
	 */
	public static void main(String[] args) {
		// 03. 変数作成
		int value01 = 15;
		int value02 = 3;
		
		// 04. インスタンス生成 (四則演算クラス)
		MathOperationsClass mathOperationsInstance = new MathOperationsClass();
		
		// 05. 処理
		System.out.println("▼ 電卓システム");
		System.out.println("・加算: " + value01 + " + " + value02 + " = " + mathOperationsInstance.mathAddition(value01, value02));
		System.out.println("・減算: " + value01 + " - " + value02 + " = " + mathOperationsInstance.mathSubtraction(value01, value02));
		System.out.println("・乗算: " + value01 + " × " + value02 + " = " + mathOperationsInstance.mathMultiplicationn(value01, value02));
		System.out.println("・除算: " + value01 + " ÷ " + value02 + " = " + mathOperationsInstance.mathDivision(value01, value02));
	}
}

実行結果
▼ 電卓システム
・加算: 15 + 3 = 18
・減算: 15 – 3 = 12
・乗算: 15 × 3 = 45
・除算: 15 ÷ 3 = 5

コメント

補足
コード中にある『// 文章』はコメントと呼びます。
コード自体には影響がなく、人が認識するために使用されます。

基本のコード: オブジェクトに関わる機能

1. プロパティ

/**
 * プロパティ付与の変数クラス
 */
public class SamplePropertyClass {
	public String value01 = "公開";
	private String value02 = "非公開";
}
/**
 * プロパティ変数呼び出しクラス
 */
public class CallValueClass {

	public static void main(String[] args) {
		// インスタンス生成
		SamplePropertyClass valueInstance = new SamplePropertyClass();
		
		// プロパティ付与済みの変数呼び出し
		System.out.println("public: " + valueInstance.value01);

		// エラーのためコメントアウト
		// System.out.println("private: " + valueInstance.value02); 
	}
}

実行結果
public: 公開

2.コンストラクタ

public class SampleConstructorClass {
	// フィールド変数
	int value = 0;
	String result = null;

	/**
	 * コンストラクタ
	 */
	SampleConstructorClass() {
		System.out.println("▼ コンストラクタの呼び出し成功");
		value = 2024;
		result = "計算結果: ";
	}

	/**
	 * 変数表示メソッド
	 */
	public void variableDisplay() {
		System.out.println(result + value);
	}

	/**
	 * メインメソッド
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println("▼ インスタンス生成前");
		SampleConstructorClass constructorInstance = new SampleConstructorClass();

		System.out.println("▼ インスタンス生成後");
		constructorInstance.variableDisplay();
	}
}

実行結果
▼ インスタンス生成前
▼ コンストラクタの呼び出し成功
▼ インスタンス生成後
計算結果: 2024

インスタンスが生成(new)されるとコンストラクタが呼ばれます。

フィールド変数
メソッド内ではなく、クラス内で設定される変数
基本的に、宣言するならprivateのプロパティを付与する(今回はサンプルの為例外)

3.オーバーロード

public class SampleOverloadMainClass {
	public static void main(String[] args) {
		// インスタンス生成
		SampleOverloadSubClass overloadInstance = new SampleOverloadSubClass();
		
		// 引数なしメソッドの呼び出し
		overloadInstance.sampleCallmethod();
		
		// 引数ありメソッドの呼び出し
		overloadInstance.sampleCallmethod("オーバーロードの成功!!");
	}
}
public class SampleOverloadSubClass {
	/**
	 * 引数なしメソッド
	 */
	public void sampleCallmethod(){
		System.out.println("▼ 引数なしのメソッドが実行されました");
	}
	
	/**
	 * 引数ありメソッド
	 */
	public void sampleCallmethod(String sample){
		System.out.println("▼ 引数ありのメソッドが実行されました");
		System.out.println("値: " + sample);
	}
}

実行結果
▼ 引数なしのメソッドが実行されました
▼ 引数ありのメソッドが実行されました
値: オーバーロードの成功!!

Null
“”(空白文字)と違い、なにもない。空の状態

オブジェクト指向の代表的コード

1. 継承

/**
 * 親クラス(継承元クラス)
 */
public class SampleParentClass {
	String name = "親ねこ";

	public void callCat() {
		System.out.println("▼ 親クラスのメソッドが呼び出されました");
		System.out.println(name);
	}
}
/**
 * 子クラス
 */
public class SampleChildClass extends SampleParentClass {
	public void changeCat(){
		System.out.println("▼ 子クラスのメソッドが呼び出されました");
		name = "子ねこ"; 
	}
}
public class SampleInheritanceMainClass {

	public static void main(String[] args) {
		// 子クラスのインスタンス生成
		SampleChildClass childInstance = new SampleChildClass();
		
		// 親クラスのメソッド呼び出し
		childInstance.callCat();
		
		// 子クラスのメソッド呼び出し
		childInstance.changeCat();
				
		// 親クラスのメソッド呼び出し
		childInstance.callCat();
	}
}

実行結果
▼ 親クラスのメソッドが呼び出されました
親ねこ
▼ 子クラスのメソッドが呼び出されました
▼ 親クラスのメソッドが呼び出されました
子ねこ

子クラスは親クラスのオブジェクトを引き継げます。

2. カプセル化

/**
 * 生徒のデータクラス
 */
public class SampleStudentsDataClass {
	// 学籍番号
	private String student_id;

	/**
	 * ゲッタ
	 */
	public String getStudent_id() {
		return student_id;
	}

	/**
	 * セッタ
	 */
	public void setStudent_id(String student_id) {
		this.student_id = student_id;
	}
}
public class SampleCapsuleClass {

	public static void main(String[] args) {
		// インスタンス生成
		SampleStudentsDataClass studentsDataInstance = new SampleStudentsDataClass();

		// データのセット
		studentsDataInstance.setStudent_id("2024040A14");

		// データの取得・表示
		System.out.println("学籍番号: " + studentsDataInstance.getStudent_id());
	}
}

実行結果
学籍番号: 2024040A14

上記の仕組みをゲッタ/セッタと呼びます。

悪意のある第三者が容易にデータを取得し辛くなる効果があります。
そしてデータを関連付けしてクラス毎でまとめればコードの可読性も向上します。

3. ポリモーフィズム

ポリモーフィズムを実装する際、Javaで2つの実装方法をご紹介します。

抽象化クラス

抽象化クラスを使ったポリモーフィズムの実装を行います。

/**
 * 抽象化クラス
 */
abstract class SampleAbstractClass {
	// フィールド変数
	String type;
	String feature;
	int legs;
	String meal;

	/**
	 * 基本情報のセット
	 */
	void setCommonInformation(String type, String feature, int legs) {
		this.type = type;
		this.feature = feature;
		this.legs = legs;
		System.out.print("種族:" + type + ", 特性:" + feature + ", 足の数:" + legs);
	}

	/**
	 * 抽象の動物情報メソッド
	 */
	abstract String animalInformation();
}
/**
 * ねこの具体化クラス
 */
public class SampleEntityCatClass extends SampleAbstractClass {
	// フィールド変数
	String kind;

	/**
	 * ねこの模様設定コンストラクタ
	 */
	SampleEntityCatClass(String kind) {
		this.kind = kind;
	}

	/** 
	 * 動物情報のオーバーライド
	 */
	@Override
	String animalInformation() {
		return ", 模様:" + kind;
	}
}
/**
 * 鳥の具体化クラス
 */
public class SampleEntityBirdClass extends SampleAbstractClass {
	// フィールド変数
	String skill;
	String size;

	/**
	 * 鳥の能力・設定コンストラクタ
	 */
	SampleEntityBirdClass(String skill, String size) {
		this.skill = skill;
		this.size = size;
	}

	/** 
	 * 動物情報のオーバーライド
	 */
	@Override
	String animalInformation() {
		return (", 能力:" + skill + ", 大きさ:" + size);
	}
}
/**
 * メインクラス
 */
public class AbstractMainClass {

	public static void main(String[] args) {
		// ねこクラスの処理
		SampleEntityCatClass EntityCatInstance = new SampleEntityCatClass("サバトラ");
		EntityCatInstance.setCommonInformation("ねこ", "もふもふの毛並み", 10);
		System.out.println(EntityCatInstance.animalInformation());
		
		// 鳥クラスの処理
		SampleEntityBirdClass EntityBirdInstance = new SampleEntityBirdClass("飛ぶ", "大");
		EntityBirdInstance.setCommonInformation("鳥", "シャープな嘴", 2);
		System.out.println(EntityBirdInstance.animalInformation());
	}
}

実行結果
種族:ねこ, 特性:もふもふの毛並み, 足の数:10, 模様:サバトラ
種族:鳥, 特性:シャープな嘴, 足の数:2, 能力:飛ぶ, 大きさ:大

抽象化クラスの構成と強みは下記です。
抽象化クラス(共通の処理まとめる)→具体化クラス(細かい差異を個別のクラスで実装)

なお、抽象クラスの具体化クラスには必ずオーバーライドを実装します。
無いとエラーが出ます。

this.変数
Javaではオブジェクトに『this』を付けると当クラスで宣言したオブジェクトを指すという意味になります
継承・同名の引数があるなど、同名のオブジェクトがある場合に使用します

抽象クラスはnew演算子でインスタンス生成ができません

インターフェース

インターフェースを使ったポリモーフィズムの実装を行います。

/**
 * インターフェースクラス
 */
interface SampleInterfaceClass {
	// シグニチャ定義
	void animalCry();
}
/** 
 * インターフェースの実装クラス
 */
public class CatClass implements SampleInterfaceClass{

	/**
	 * インターフェースの中身を実装
	 */
	public void animalCry() {
		System.out.println("にゃー");
	}
}
/** 
 * インターフェースの実装クラス
 */
public class DogClass implements SampleInterfaceClass{
	/**
	 * インターフェースの中身を実装
	 */
	public void animalCry() {
		System.out.println("ワン!!");
	}
}
/**
 * メインクラス(確認用)
 */
public class InterfaceMainClass {

	public static void main(String[] args) {
		// インスタンス生成
		SampleInterfaceClass cat = new CatClass();
		SampleInterfaceClass dog = new DogClass();

		System.out.print("猫: ");
		cat.animalCry();

		System.out.print("犬: ");
		dog.animalCry();
	}
}

実行結果
猫: にゃー
犬: ワン!!

インターフェースの強みは同目的の類似処理をまとめられる点です。

他にもインターフェースのメリットとしては下記が挙げられます。
・仕様変更に強い
・全体的に簡潔なコードが書ける
・クラス型が同じでも、違う処理を実行可能

『インターフェース』と『抽象クラス』の使い分け

インターフェース
メソッドを完全に実装と分ける場合

抽象クラス
親クラスに共通処理を実装したい場合

最初のうちは『インターフェース』と『抽象クラス』はポリモーフィズムを実現するための手段の1つだと考えておいてください。

おすすめの勉強方法

オブジェクト指向とプログラミング言語の勉強おすすめは下記です。

  1. ここでもどこのサイトでもよいので概要を見て、情報を理解・整理する
  2. 本で詳細を理解する
  3. 実際にプログラミングを行う(1番大事)
  4. 分からなくなったら概要を見たり、本を読みなおす

そしてプログラミング言語を勉強する場合は1つの言語を極めてから他の言語を習得するのがおすすめです。

どの言語も基本的な機能は大体同じなので複数の言語に手を出すよりも、1つを極める方が効率的だと思います。

ある程度慣れてきたらば公式ドキュメントが1番の資料です。

最後に

ひとえに変数やメソッドといっても、数多の種類があります。
オブジェクトを使いこなせるようになれば、質の高いコーディングができるようになりますよ。

プログラミングは奥が深いのでぜひ自分の手で試してスキルアップをおすすめします。

シェアお願いします!
  • URLをコピーしました!

この記事を書いた人

ご閲覧ありがとうございます。
少しでも、プラスになれたのなら幸いです。

コメント

コメントする

コメントは日本語で入力してください。(スパム対策)

CAPTCHA

目次