Java基礎#6 オブジェクト指向プログラミング(OOP)の基礎
〜2月17日 14:30
クラスとオブジェクトの概念
Javaにおけるクラスとオブジェクトは、オブジェクト指向プログラミングの中核を成す概念です。
クラスは、オブジェクトの設計図や雛形として機能します。具体的には、オブジェクトが持つ属性(フィールド)と振る舞い(メソッド)を定義します。
例えば、「車」というクラスを考えると、色や型番などの属性と、走行や停止などの振る舞いを定義することができます。
class Car {
String color;
String model;
void drive() {
System.out.println("車が走ります");
}
void stop() {
System.out.println("車が止まります");
}
}
一方、オブジェクトはクラスから生成される実体です。
クラスが設計図なら、オブジェクトはその設計図に基づいて作られた具体的な製品と言えます。
オブジェクトは、クラスで定義されたフィールドとメソッドを持ち、それらを使用して様々な操作を行います。
Car myCar = new Car();
myCar.color = "赤";
myCar.model = "スポーツカー";
myCar.drive();
この例では、CarクラスからmyCarというオブジェクトを生成し、そのフィールドに値を設定し、メソッドを呼び出しています。
クラスとオブジェクトの関係は、クッキーの型とクッキーの関係に例えることができます。
クラスはクッキーの型で、オブジェクトは実際に焼かれたクッキーです。
同じ型から複数のクッキーを作れるように、一つのクラスから複数のオブジェクトを生成できます。
オブジェクト指向プログラミングの利点には、コードの再利用性の向上、プログラムの構造化、保守性の向上などがあります。
例えば、「車」クラスを一度定義すれば、それを基に多くの車オブジェクトを作成でき、各オブジェクトは独自の属性値を持つことができます。
また、クラスを使用することで、関連するデータとメソッドを一つの単位にまとめる「カプセル化」が可能になります。
これにより、コードの整理と管理が容易になり、大規模なプログラムの開発や保守が効率的に行えるようになります。
Javaでは、クラスからオブジェクトを生成する過程を「インスタンス化」と呼び、生成されたオブジェクトを「インスタンス」とも呼びます。
このプロセスにより、クラスで定義された抽象的な概念が、メモリ上に具体的なデータとして存在するようになります。
フィールドとメソッド
Javaにおけるフィールドとメソッドは、クラスの主要な構成要素です。
フィールド
フィールドは、クラスが持つ属性や状態を表す変数です。
クラス内で宣言され、そのクラスのインスタンスに関連付けられたデータを保持します。
class Person {
String name;
int age;
}
この例では、`name`と`age`がフィールドです。
フィールドにはデフォルト値が設定されますが、明示的に初期化することもできます。
フィールドへのアクセスは、通常、ドット記法を使用して行います:
Person p = new Person();
p.name = "Alice";
p.age = 25;
フィールドには、`static`修飾子を付けてクラス変数として宣言することもできます。
これらは全てのインスタンスで共有される値を持ちます。
メソッド
メソッドは、クラスの振る舞いや機能を定義します。
メソッドは特定の処理を実行し、必要に応じて値を返します。
class Calculator {
int add(int a, int b) {
return a + b;
}
void printResult(int result) {
System.out.println("結果: " + result);
}
}
この例では、`add`メソッドは2つの整数を受け取り、その和を返します。
`printResult`メソッドは結果を表示するだけで、値を返しません(`void`)。
メソッドの呼び出しもドット記法を使用します:
Calculator calc = new Calculator();
int sum = calc.add(5, 3);
calc.printResult(sum);
フィールドとメソッドの関係
メソッドはしばしばフィールドの値を操作したり、フィールドの値に基づいて処理を行ったりします。
例えば:
class BankAccount {
private double balance;
void deposit(double amount) {
balance += amount;
}
double getBalance() {
return balance;
}
}
この`BankAccount`クラスでは、`deposit`メソッドが`balance`フィールドを更新し、`getBalance`メソッドが現在の残高を返します。
フィールドとメソッドを適切に組み合わせることで、オブジェクト指向プログラミングの基本原則であるカプセル化を実現できます。
プライベートフィールドとパブリックメソッド(ゲッターとセッター)を使用することで、データの整合性を保ちながら、外部からのアクセスを制御できます。
フィールドとメソッドを効果的に使用することで、クラスの設計をより柔軟かつ保守性の高いものにすることができます。
これにより、Javaプログラムの構造化と再利用性が向上します。
コンストラクタ
Javaのコンストラクタは、クラスのインスタンスを生成する際に呼び出される特殊なメソッドです。
コンストラクタはクラス名と同じ名前を持ち、戻り値を持ちません。
主な役割は、オブジェクトの初期化です。
コンストラクタの基本的な構文は以下の通りです:
public class ClassName {
public ClassName() {
// 初期化処理
}
}
コンストラクタは、newキーワードを使用してオブジェクトを生成する際に自動的に呼び出されます:
ClassName object = new ClassName();
コンストラクタには引数を持たせることができ、これによりオブジェクト生成時に初期値を設定できます:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Person person = new Person("Alice", 30);
また、一つのクラスに複数のコンストラクタを定義することも可能です。
これをコンストラクタのオーバーロードと呼びます:
public class Car {
private String model;
private String color;
public Car() {
this.model = "Unknown";
this.color = "White";
}
public Car(String model) {
this.model = model;
this.color = "White";
}
public Car(String model, String color) {
this.model = model;
this.color = color;
}
}
コンストラクタ内で他のコンストラクタを呼び出すこともできます。
これにはthis()を使用します:
public Car() {
this("Unknown", "White");
}
コンストラクタを適切に設計することで、オブジェクトの一貫性と信頼性を確保できます。
また、コードの再利用性と保守性も向上します。
例えば、銀行口座を表すクラスでコンストラクタを使用する例を考えてみましょう:
public class BankAccount {
private String accountNumber;
private double balance;
public BankAccount(String accountNumber) {
this(accountNumber, 0.0);
}
public BankAccount(String accountNumber, double initialBalance) {
this.accountNumber = accountNumber;
this.balance = initialBalance;
}
}
この例では、口座番号のみを指定するコンストラクタと、口座番号と初期残高を指定するコンストラクタを提供しています。
これにより、新規口座の作成時に柔軟性を持たせることができます。
コンストラクタを効果的に活用することで、オブジェクト指向プログラミングの利点を最大限に活かし、より堅牢で保守性の高いJavaプログラムを作成することができます。
カプセル化とアクセサ(getter/setter)
Javaにおけるカプセル化は、オブジェクト指向プログラミングの重要な概念の1つです。
カプセル化の主な目的は、クラスの内部データを外部から直接アクセスできないようにし、データの整合性を保護することです。
カプセル化を実現するための主な手法は以下の通りです:
フィールドをprivateにする
アクセサメソッド(getterとsetter)を提供する
例えば、以下のようなPersonクラスを考えてみましょう:
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 0 && age <= 120) {
this.age = age;
} else {
System.out.println("Invalid age");
}
}
}
このクラスでは、nameとageフィールドがprivateとして宣言されており、直接アクセスできません。
代わりに、getterとsetterメソッドを通じてこれらのフィールドにアクセスします。
getterメソッド(getName()とgetAge())は、フィールドの値を返します。setterメソッド(setName()とsetAge())は、フィールドに値を設定します。
setterメソッドでは、値の妥当性チェックを行うこともできます。
上記の例では、setAge()メソッドで年齢が0から120の範囲内であることを確認しています。
カプセル化のメリットには以下のようなものがあります:
データの隠蔽:クラスの内部実装を隠蔽し、外部からの不正なアクセスを防ぐ
柔軟性:内部実装を変更しても、外部のコードに影響を与えない
制御:setterメソッドでデータの妥当性を確認できる
カプセル化されたクラスの使用例:
public class Main {
public static void main(String[] args) {
Person person = new Person();
person.setName("Alice");
person.setAge(25);
System.out.println(person.getName() + " is " + person.getAge() + " years old.");
person.setAge(150); // Invalid age
}
}
この例では、Personクラスのオブジェクトを作成し、setterメソッドを使用してnameとageを設定しています。
getterメソッドを使用して値を取得し、表示しています。
また、無効な年齢を設定しようとすると、エラーメッセージが表示されます。
カプセル化とアクセサメソッドを適切に使用することで、データの整合性を保ちながら、クラスの使いやすさと保守性を向上させることができます。
クラスを作成し、インスタンスを生成して操作するプログラムを作成
課題
「本」を表す`Book`クラスを作成し、それを使用するプログラムを作成してください。
以下の要件を満たすようにしてください:
`Book`クラスは以下のプロパティを持つ:
タイトル(String)
著者(String)
出版年(int)
価格(double)
`Book`クラスは以下のメソッドを持つ:
コンストラクタ(全てのプロパティを初期化)
各プロパティのgetter/setterメソッド
本の情報を表示するメソッド
メインプログラムで以下の操作を行う:
`Book`クラスのインスタンスを2つ以上作成
作成したインスタンスの情報を表示
いずれかのインスタンスのプロパティを変更し、再度表示
回答例
ここから先は
1月18日 14:30 〜 2月17日 14:30
Amazonギフトカード5,000円分が当たる
サポートもお待ちしております! 頂いたサポートは今後の創作活動費用として、noteとYouTubeに活用させていただければと考えております!