はじめに
この記事では、カプセル化の概念について解説し、具体的なコンソールアプリの例を通じて、カプセル化の実践的な適用を紹介します。
使用技術
- .NET: Microsoftによって開発された、様々なアプリケーションを作成するためのソフトウェアフレームワーク。
- C#: オブジェクト指向のプログラミング言語で、.NETフレームワーク上で動作します。
- Visual Studio: コードの記述、デバッグ、コンパイルなどを行うためのMicrosoftの統合開発環境(IDE)。
- OpenWeatherMap API: 全世界の天気情報を提供するWebサービスのAPI。
オブジェクト指向プログラミングにおけるカプセル化
カプセル化とは、クラスの内部データや実装の詳細を外部から隠蔽し、外部からの直接アクセスを制限することです。
お天気アプリ
このお天気アプリは、都市を選択し、選ばれた都市の現在の天気情報を取得し表示するシンプルなコンソールアプリケーションです。
OpenWeatherMap APIを用いて、選択された都市の気温、湿度、風速などの天気データを取得し、コンソールに出力します。
カプセル化のメリット
コードの保護と安全性
クラス内部のデータやメソッドを外部から隠蔽し、不正アクセスや誤った使用を防ぎます。
メンテナンスのしやすさ
内部実装が隠されているため、外部からの依存が少なく、コードの変更や拡張が容易になります。
再利用性の向上
カプセル化されたクラスは、その内部実装を知らなくても使用することができます。そのため、異なるプロジェクトでの再利用がしやすくなります。
カプセル化の実践方法
適切なアクセスレベルの設定
カプセル化を実践する際には、プライベート(private)アクセス修飾子を使用して、クラスの内部実装を隠蔽します。
これにより、外部から不適切にアクセスされたり、変更されたりするのを防ぎます。一方で、必要な機能のみをパブリック(public)インターフェースとして提供します。
クラスの責務を明確に定義する
クラスの責務を明確にし、関連する機能やデータのみを含めることで、クラスをより理解しやすく、再利用しやすくします。
カプセル化の実装例
-
Program.cs
:- ユーザーから都市の選択を受け付けるインターフェイス。
-
WeatherService
クラスを使って選ばれた都市の天気データを取得。(APIキーやHTTPクライアントの詳細は露出しない。) - 取得した天気データをコンソールに表示。
-
WeatherService.cs
:- 天気データ取得のためのロジックをカプセル化。
- APIキーとHTTPクライアントをプライベート変数で隠蔽。
- 外部からの天気データ取得のための公開メソッドを提供。
Program.cs
using System.Text.Json;
string apiKey = "APIキー"; // OpenWeatherMapのAPIキーを設定。
var weatherService = new WeatherService(apiKey); // WeatherServiceクラスのインスタンスを作成。
// 日本の主要都市とその英語名のマッピングをDictionaryで定義。
var cityMap = new Dictionary<int, (string JapaneseName, string EnglishName)>
{
{ 1, ("東京", "Tokyo") },
{ 2, ("大阪", "Osaka") },
{ 3, ("名古屋", "Nagoya") },
{ 4, ("福岡", "Fukuoka") },
{ 5, ("札幌", "Sapporo") },
};
Console.WriteLine("都市を選んでください:");
// 利用可能な都市のリストをコンソールに表示。
foreach (var city in cityMap)
{
Console.WriteLine($"{city.Key}. {city.Value.JapaneseName}");
}
(string JapaneseName, string EnglishName) selectedCityTuple;
int selectedNumber;
while (true)
{
Console.Write("番号を入力してください (1-5): ");
// ユーザーからの入力を受け取り、選択された都市を識別。
if (int.TryParse(Console.ReadLine(), out selectedNumber) && cityMap.TryGetValue(selectedNumber, out selectedCityTuple))
{
break;
}
Console.WriteLine("無効な入力です。1から5までの数字を入力してください。");
}
string selectedCity = selectedCityTuple.EnglishName;
try
{
// 選択された都市に基づいて天気データを非同期で取得。
string weatherData = await weatherService.GetWeatherDataAsync(selectedCity);
var weatherJson = JsonDocument.Parse(weatherData);
// 取得した天気データをコンソールに表示。
Console.WriteLine($"場所: {weatherJson.RootElement.GetProperty("name").GetString()}");
Console.WriteLine($"天気: {weatherJson.RootElement.GetProperty("weather")[0].GetProperty("description").GetString()}");
Console.WriteLine($"現在の気温: {weatherJson.RootElement.GetProperty("main").GetProperty("temp").GetDouble()}°C");
Console.WriteLine($"最高気温: {weatherJson.RootElement.GetProperty("main").GetProperty("temp_max").GetDouble()}°C");
Console.WriteLine($"最低気温: {weatherJson.RootElement.GetProperty("main").GetProperty("temp_min").GetDouble()}°C");
Console.WriteLine($"湿度: {weatherJson.RootElement.GetProperty("main").GetProperty("humidity").GetDouble()}%");
Console.WriteLine($"風速: {weatherJson.RootElement.GetProperty("wind").GetProperty("speed").GetDouble()} m/s");
}
catch (Exception ex)
{
// 天気データ取得中の例外をキャッチし、エラーメッセージを表示。
Console.WriteLine($"エラーが発生しました: {ex.Message}");
}
WeatherService.cs
using System;
using System.Net.Http;
using System.Threading.Tasks;
public class WeatherService
{
private readonly string apiKey; // APIキーをプライベート変数として保持し、外部からのアクセスを制限しています。
private readonly HttpClient httpClient; // HttpClientのインスタンスもプライベート変数として隠蔽しています。
public WeatherService(string apiKey)
{
this.apiKey = apiKey; // コンストラクタでAPIキーを初期化。
httpClient = new HttpClient(); // HttpClientのインスタンスを作成。
}
public async Task<string> GetWeatherDataAsync(string city)
{
try
{
string requestUri = BuildRequestUri(city); // 非公開のBuildRequestUriメソッドを使用して、リクエストURIを生成。
HttpResponseMessage response = await httpClient.GetAsync(requestUri); // HttpClientを使用してリクエストを非同期で送信。
if (response.IsSuccessStatusCode)
{
string weatherData = await response.Content.ReadAsStringAsync(); // レスポンスから天気データを読み取る。
return weatherData;
}
else
{
return $"天気データの取得に失敗しました: {response.StatusCode}"; // レスポンスが失敗だった場合のエラーメッセージ。
}
}
catch (HttpRequestException e)
{
return $"リクエストエラー: {e.Message}"; // HTTPリクエストの例外処理。
}
}
private string BuildRequestUri(string city)
{
return $"https://api.openweathermap.org/data/2.5/weather?q={city},jp&appid={apiKey}&units=metric&lang=ja";
// URIを構築する非公開メソッド。
}
}