Skip to content

第10章 クラスについて掘り下げる

この章では、第 7 章から学習してきたクラスについて、より実践的な使い方を学習します。

第 7 章では、クラスとオブジェクトの基本、プロパティ、メソッドを学びました。 第 8 章では static、第 9 章では .NET の標準クラスを使ってきました。

この章では、自分で作るクラスを 使いやすく、安全に するための機能を扱います。

さまざまな型を返すメソッド(int、bool、自作クラスなど)
メソッドのオーバーロード(同名メソッドの複数定義)
省略可能な引数
コンストラクター(オブジェクト作成時の初期化)
プロパティの高度な使い方(get/set、読み取り専用、private set)

これらは、オブジェクト指向プログラミングで重要な カプセル化(オブジェクトの中身を守る考え方)につながります。 この章では難しく考えすぎず、まずは次のように理解することを目指します。

オブジェクトを作るときに必要な値を確実に設定する
不正な値が入らないようにする
外から変更してよい値と、変更させたくない値を分ける

この章でできるようになること

Section titled “この章でできるようになること”

この章を終えると、次のことができるようになります。

  • メソッドが intstringbool・自作クラスなど、さまざまな型を返せることを説明できる
  • メソッドのオーバーロードを定義できる
  • 省略可能な引数を持つメソッドを定義できる
  • 名前付き引数で呼び出せる
  • 引数付きコンストラクターを定義できる
  • コンストラクターをオーバーロードできる
  • this(...) で別のコンストラクターを呼び出せる
  • get / set を明示したプロパティを書ける
  • value の意味を説明できる
  • 読み取り専用プロパティを作成できる
  • private set で外部からの変更を制限できる
  • プロパティに初期値を設定できる
  • アクセス修飾子(public / private)の意味と使い分けを説明できる
  • カプセル化が目指す 3 つのこと(状態を隠す / 操作を限定する / 不正な状態を作らせない)を説明できる

項目内容
開発環境Visual Studio 2022
プロジェクト種類コンソール アプリ
対象フレームワーク.NET 8
ソリューション名Chapter10
プロジェクト名Ch10_ClassDetails

csproj の Nullable は disable に変更してください

プロジェクト作成後、Ch10_ClassDetails.csproj を開き、<Nullable>disable</Nullable> に変更してください。

詳しい手順は、第 1 章「1-1 プロジェクトを作成する」を参照してください。


作業を始める前に、次の内容を確認してください。

  • クラスを別ファイル(Employee.cs など)に作成できる(第 7 章)
  • プロパティ・メソッドを定義できる
  • 戻り値のあるメソッド・引数のあるメソッドを書ける
  • 静的メソッドとインスタンスメソッドの違いを説明できる
  • 第 9 章の内容を Git に提出済みである

10-1 メソッドはどんな型でも返せる

Section titled “10-1 メソッドはどんな型でも返せる”

メソッドは、結果を呼び出し元に返すことができます。これを 戻り値 といいます。 戻り値の型は、intstringbool などの基本型だけでなく、自作クラスの型 も指定できます。

戻り値の型
int計算結果(金額、点数)
string表示用文字列
bool判定結果(合格か否か)
自作クラスオブジェクトそのもの

intstring を返すメソッドは、これまでにも書いてきました。この章では、特に bool を返すメソッド自作クラスを返すメソッド を中心に見ていきます。あわせて、int / string を返すメソッドの より実用的な書き方(条件で結果を切り替える / 計算結果をまとめる)もバリエーションとして取り上げます。


条件判定の結果を bool で返すメソッドはよく使います。 次の例では、点数が合格点(60 点)以上かどうかを判定します。

TestResult.cs:

TestResult.cs
namespace Ch10_ClassDetails;
class TestResult
{
public string EmployeeName { get; set; }
public int Score { get; set; }
public bool IsPassed()
{
return Score >= 60;
}
}

Program.cs:

Program.cs
namespace Ch10_ClassDetails;
internal class Program
{
static void Main(string[] args)
{
TestResult result = new TestResult
{
EmployeeName = "山田二郎",
Score = 75
};
if (result.IsPassed())
{
Console.WriteLine($"{result.EmployeeName}:合格");
}
else
{
Console.WriteLine($"{result.EmployeeName}:不合格");
}
}
}

実行結果:

山田二郎:合格

IsPassed メソッドは Score >= 60 の結果(true または false)をそのまま返しています。 bool を返すメソッドは、if 文の条件としてそのまま使えます。

補足:Is〇〇Has〇〇Can〇〇

bool を返すメソッドの名前は、Is〇〇(〇〇か?)、Has〇〇(〇〇を持つか?)、Can〇〇(〇〇できるか?)のような形にすると、if 文で読みやすくなります。


string 型は、これまでも何度も返してきました。ここでは、条件に応じて返す文字列を切り替える パターンを見ます。 次の例では、点数から評価ランク("A"/"B"/"C"/"D")を返します。

Grader.cs:

Grader.cs
namespace Ch10_ClassDetails;
class Grader
{
public string GetGrade(int score)
{
if (score >= 80) return "A";
if (score >= 60) return "B";
if (score >= 40) return "C";
return "D";
}
}

Program.cs:

Grader grader = new Grader();
Console.WriteLine($"85点:{grader.GetGrade(85)}");
Console.WriteLine($"55点:{grader.GetGrade(55)}");
Console.WriteLine($"30点:{grader.GetGrade(30)}");

実行結果:

85点:A
55点:B
30点:D

ポイント:

  • if の条件に当てはまった瞬間に return している
  • return が実行されると その時点でメソッドは終わる ため、それ以降の if は判定されない
  • 最後の return "D"; は、上のどれにも当てはまらなかったときの「それ以外」を表す

このように「条件で結果が変わる文字列を返す」のは、表示用文字列やラベル取得などで頻出のパターンです。


数値計算の結果を int で返すメソッドも、業務でよく登場します。 次の例では、基本給と手当の合計、賞与(月給 × か月数)を返します。

SalaryCalculator.cs:

SalaryCalculator.cs
namespace Ch10_ClassDetails;
class SalaryCalculator
{
public int GetTotalSalary(int baseSalary, int allowance)
{
return baseSalary + allowance;
}
public int GetBonus(int monthlySalary, int months)
{
return monthlySalary * months;
}
}

Program.cs:

SalaryCalculator calc = new SalaryCalculator();
int total = calc.GetTotalSalary(300000, 50000);
int bonus = calc.GetBonus(300000, 2);
Console.WriteLine($"総支給額:{total}");
Console.WriteLine($"賞与(2か月分):{bonus}");

実行結果:

総支給額:350000円
賞与(2か月分):600000円

メソッドが「入力(引数)から 出力(戻り値)を作る装置」になっているのが分かります。 同じ計算を 2 か所以上で使うときは、毎回式を書くよりメソッドにまとめると、読みやすく、間違いも減ります。


メソッドは、自作クラスのオブジェクト を返すこともできます。 たとえば「サンプル用の社員を作って返す」というメソッドを用意できます。

補足:この節で使う Employee クラスについて

次のサンプルは、第 7 章で作成した Employee クラスをそのまま使います。 同じプロジェクトに Employee.cs を追加し、次の 3 つのプロパティを定義してください。

Employee.cs
namespace Ch10_ClassDetails;
class Employee
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public string DepartmentName { get; set; }
}

EmployeeFactory.csEmployee.csnamespace を同じ Ch10_ClassDetails に揃えると、using を書かなくても互いに参照できます。

EmployeeFactory.cs:

EmployeeFactory.cs
namespace Ch10_ClassDetails;
static class EmployeeFactory
{
public static Employee CreateSampleEmployee()
{
return new Employee
{
EmployeeId = 1001,
EmployeeName = "山田二郎",
DepartmentName = "総務"
};
}
}

Program.cs:

Program.cs
namespace Ch10_ClassDetails;
internal class Program
{
static void Main(string[] args)
{
Employee employee = EmployeeFactory.CreateSampleEmployee();
Console.WriteLine($"{employee.EmployeeId}:{employee.EmployeeName}({employee.DepartmentName})");
}
}

実行結果:

1001:山田二郎(総務)

戻り値の型に Employee と書いています。

public static Employee CreateSampleEmployee()

このメソッドは、Employee クラスのオブジェクトを返します。 この書き方は、後の章で扱うリストやコレクションでもよく使う形です。


戻り値の型と return の型は一致させる

Section titled “戻り値の型と return の型は一致させる”

メソッドの戻り値の型と、return で返す値の型は、必ず一致 している必要があります。

public int GetAmount()
{
return "900"; // ← エラー:int を返す約束なのに string を返している
}

戻り値の型が int なら int を、string なら string を、Employee なら Employee を返します。


10-2 メソッドのオーバーロード

Section titled “10-2 メソッドのオーバーロード”

オーバーロード とは、同じ名前で引数の異なるメソッドを複数定義する ことです。

これまでも、知らないうちにオーバーロードを使ってきました。

Console.WriteLine("こんにちは");
Console.WriteLine(100);
Console.WriteLine(true);

同じ WriteLine という名前でも、文字列・数値・真偽値など、さまざまな型を渡せます。 これは Console.WriteLine多数のオーバーロード を持っているためです。


社員検索用の Search メソッドを、社員番号でも氏名でも呼べるようにします。

EmployeeSearchService.cs:

EmployeeSearchService.cs
namespace Ch10_ClassDetails;
class EmployeeSearchService
{
public void Search(int employeeId)
{
Console.WriteLine($"社員番号 {employeeId} で検索します。");
}
public void Search(string employeeName)
{
Console.WriteLine($"氏名 {employeeName} で検索します。");
}
}

Program.cs:

Program.cs
namespace Ch10_ClassDetails;
internal class Program
{
static void Main(string[] args)
{
EmployeeSearchService service = new EmployeeSearchService();
service.Search(1001);
service.Search("山田");
}
}

実行結果:

社員番号 1001 で検索します。
氏名 山田 で検索します。

どちらも Search という名前ですが、引数の が違うので、C# は呼び出し時にどちらを使うか判断できます。


引数の数が違うオーバーロード

Section titled “引数の数が違うオーバーロード”

引数の が違ってもオーバーロードできます。

class ReportPrinter
{
public void Print(string title)
{
Console.WriteLine($"タイトル:{title}");
}
public void Print(string title, string date)
{
Console.WriteLine($"タイトル:{title}");
Console.WriteLine($"日付:{date}");
}
}
呼び出し動作
printer.Print("売上レポート")タイトルだけ表示
printer.Print("売上レポート", "2026/05/18")タイトルと日付を表示

オーバーロードは 3 つ以上でも定義できます。 業務コードでは、引数の組み合わせを変えた 3〜5 個のオーバーロードを持つメソッドは珍しくありません。

次の PriceFormatter は、価格表示のオーバーロードを 3 つ持ちます。

PriceFormatter.cs:

PriceFormatter.cs
namespace Ch10_ClassDetails;
class PriceFormatter
{
public string Format(int price)
{
return $"{price}";
}
public string Format(int price, string label)
{
return $"{label}:{price}";
}
public string Format(int price, string label, int quantity)
{
return $"{label}:{price}円 × {quantity}個 = {price * quantity}";
}
}

呼び出し:

PriceFormatter formatter = new PriceFormatter();
Console.WriteLine(formatter.Format(180));
Console.WriteLine(formatter.Format(180, "ノート"));
Console.WriteLine(formatter.Format(180, "ノート", 5));

実行結果:

180円
ノート:180円
ノート:180円 × 5個 = 900円

引数を 「少しずつ詳しくしていく」 発想は、Console.WriteLine(値だけ表示 → 書式付き表示 → 複数の値を埋め込み表示)など、.NET の標準クラスでもよく見られるパターンです。

補足:オーバーロードと省略可能な引数、どちらを使う?

上の PriceFormatter は、次に学ぶ「省略可能な引数」(10-3)でも書けます。

public string Format(int price, string label = "", int quantity = 1) { ... }

どちらを使うかは状況によります。引数の組み合わせごとに処理がはっきり違う場合はオーバーロード既定値で動かしたいだけの場合は省略可能な引数 が読みやすくなります。 迷ったときは、章末「よくあるつまずき」や配属先のコード規約を参考にしてください。


戻り値の型だけが違うメソッド は、オーバーロードできません。

public int GetValue()
{
return 100;
}
public string GetValue() // ← エラー
{
return "100";
}

呼び出すときに引数だけでは区別できないためです。

オーバーロードできる条件
引数の が違うSearch(int)Search(string)
引数の が違うPrint(string)Print(string, string)
戻り値の型だけが違う❌ できない

メソッドの引数に 既定値 を設定しておくと、呼び出し時に省略できます。

class GreetingService
{
public string CreateMessage(string employeeName, string title = "さん")
{
return $"{employeeName}{title}、こんにちは。";
}
}

Program.cs:

Program.cs
namespace Ch10_ClassDetails;
internal class Program
{
static void Main(string[] args)
{
GreetingService service = new GreetingService();
Console.WriteLine(service.CreateMessage("山田二郎"));
Console.WriteLine(service.CreateMessage("田中浩介", "先生"));
}
}

実行結果:

山田二郎さん、こんにちは。
田中浩介先生、こんにちは。

title を省略すると、既定値の "さん" が使われます。


省略可能な引数は、必ず通常の引数の 後ろ に書きます。

// OK
public int GetPayment(int unitPrice, int quantity, int discount = 0)
// エラー
public int GetPayment(int discount = 0, int unitPrice, int quantity)

省略可能な引数を前に置くと、どの引数を省略したのか判断できなくなるためです。


省略可能な引数を組み合わせて、名前付き引数 で呼び出すこともできます。

class ReportService
{
public void PrintReport(string title, bool includeDate = false)
{
Console.WriteLine($"タイトル:{title}");
if (includeDate)
{
Console.WriteLine($"作成日:{DateTime.Today.ToString("yyyy/MM/dd")}");
}
}
}

呼び出し例:

service.PrintReport("売上レポート", includeDate: true);

引数名: 値 の形で書くと、何の引数なのかが読みやすくなります。 省略可能な引数が増えても、どれを指定したのかが明確になります。


複数の省略可能な引数を組み合わせる

Section titled “複数の省略可能な引数を組み合わせる”

省略可能な引数は、1 つだけでなく 複数並べる こともできます。 次の例では、価格表示に関する 3 つの引数(通貨単位・税込表示するか・税率)を省略可能にしています。

ProductPrinter.cs:

ProductPrinter.cs
namespace Ch10_ClassDetails;
class ProductPrinter
{
public void Print(
string productName,
int price,
string currency = "",
bool includeTax = false,
decimal taxRate = 1.10m)
{
int displayPrice = price;
if (includeTax)
{
displayPrice = (int)(price * taxRate);
}
Console.WriteLine($"{productName}:{displayPrice}{currency}");
}
}

呼び出し例:

ProductPrinter printer = new ProductPrinter();
printer.Print("ノート", 180);
printer.Print("ノート", 180, includeTax: true);
printer.Print("ノート", 180, currency: "JPY", includeTax: true);

実行結果:

ノート:180円
ノート:198円
ノート:198JPY

ポイント:

  • 既定値はそれぞれ独立して使われる(指定した引数だけ既定値から変わる)
  • 名前付き引数を使うと、途中の引数を飛ばして指定 できる(2 番目の例で currency を飛ばして includeTaxtrue に)
  • 名前付き引数を組み合わせると、引数の順序を覚えていなくても呼べる

引数が増えてきたら、名前付き引数で呼び出す側を読みやすくする のが定番です。


章前半ここまで、後半は次の節から

10-1〜10-3 で、メソッドの柔軟な書き方(戻り値の型・オーバーロード・省略可能な引数)を一通り見ました。 後半(10-4〜10-5)では、クラスの状態管理(コンストラクター、プロパティの高度な使い方、アクセス修飾子、カプセル化)に進みます。後半は本章の主役で、覚えることが多めです。


10-4 コンストラクターを使いこなす

Section titled “10-4 コンストラクターを使いこなす”

コンストラクター とは、new でオブジェクトを作成するときに 自動的に呼び出される 特別なメソッドです。

Employee employee = new Employee(); // ← この瞬間に Employee のコンストラクターが呼ばれる

主な目的は次のとおりです。

オブジェクト作成時に初期値を設定する
必要な値を必ず受け取る
不完全な状態のオブジェクトを作らせない

第 7 章では、オブジェクトを作ってからプロパティに 1 つずつ値を代入していました。 コンストラクターを使うと、作成と同時に必要な値を渡せます

Employee.cs:

Employee.cs
namespace Ch10_ClassDetails;
class Employee
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public string DepartmentName { get; set; }
public Employee(int employeeId, string employeeName, string departmentName)
{
EmployeeId = employeeId;
EmployeeName = employeeName;
DepartmentName = departmentName;
}
public string GetDisplayText()
{
return $"{EmployeeId}:{EmployeeName}({DepartmentName})";
}
}

Program.cs:

Program.cs
namespace Ch10_ClassDetails;
internal class Program
{
static void Main(string[] args)
{
Employee employee = new Employee(1001, "山田二郎", "総務");
Console.WriteLine(employee.GetDisplayText());
}
}

実行結果:

1001:山田二郎(総務)

コンストラクターの書き方の特徴

Section titled “コンストラクターの書き方の特徴”
public Employee(int employeeId, string employeeName, string departmentName)
{
EmployeeId = employeeId;
EmployeeName = employeeName;
DepartmentName = departmentName;
}

通常のメソッドと違う点は 2 つです。

項目通常メソッドコンストラクター
メソッド名自由クラス名と同じ
戻り値の型必要(void 含む)書かない

コンストラクターを使うメリット

Section titled “コンストラクターを使うメリット”

コンストラクターを使うと、オブジェクトが 作成された瞬間に必要な情報が揃っている 状態になります。

方式書き方リスク
コンストラクターなしnew してから 1 つずつ代入代入し忘れに気付きにくい
コンストラクターありnew Employee(1001, "山田二郎", "総務")引数を渡さないとコンパイルエラーになる

コンストラクターのオーバーロード

Section titled “コンストラクターのオーバーロード”

コンストラクターも、メソッドと同じようにオーバーロードできます。

Employee.cs
namespace Ch10_ClassDetails;
class Employee
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public string DepartmentName { get; set; }
public Employee()
{
EmployeeId = 0;
EmployeeName = "未設定";
DepartmentName = "未所属";
}
public Employee(int employeeId, string employeeName, string departmentName)
{
EmployeeId = employeeId;
EmployeeName = employeeName;
DepartmentName = departmentName;
}
public string GetDisplayText()
{
return $"{EmployeeId}:{EmployeeName}({DepartmentName})";
}
}

呼び出し:

Employee employee1 = new Employee();
Employee employee2 = new Employee(1001, "山田二郎", "総務");
Console.WriteLine(employee1.GetDisplayText());
Console.WriteLine(employee2.GetDisplayText());

実行結果:

0:未設定(未所属)
1001:山田二郎(総務)

this で別のコンストラクターを呼び出す

Section titled “this で別のコンストラクターを呼び出す”

複数のコンストラクターで同じ処理を書くと重複します。 : this(...)別のコンストラクターを呼び出す と、初期化処理を 1 か所にまとめられます。

class Employee
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public string DepartmentName { get; set; }
public Employee() : this(0, "未設定", "未所属")
{
}
public Employee(int employeeId, string employeeName, string departmentName)
{
EmployeeId = employeeId;
EmployeeName = employeeName;
DepartmentName = departmentName;
}
}

Employee(): this(0, "未設定", "未所属") は、「Employee(int, string, string) を呼び出してから自分の中身を実行する」という意味です。


コンストラクターで値を補正する

Section titled “コンストラクターで値を補正する”

コンストラクターの中で、簡単な値チェックを入れることもできます。

Product.cs:

Product.cs
namespace Ch10_ClassDetails;
class Product
{
public string ProductName { get; set; }
public int Price { get; set; }
public Product(string productName, int price)
{
ProductName = productName;
if (price < 0)
{
Price = 0;
}
else
{
Price = price;
}
}
}

呼び出し:

Product product = new Product("ノート", -180);
Console.WriteLine($"{product.ProductName}:{product.Price}");

実行結果:

ノート:0円

不正な値(-180)が補正され、0 が代入されました。 本格的なエラー通知は後の例外処理章で扱います。


コンストラクター内で別のメソッドを呼ぶ

Section titled “コンストラクター内で別のメソッドを呼ぶ”

コンストラクターの中身が長くなってきたら、処理を別メソッドに切り出す とすっきりします。 次の例では、値を「最小値〜最大値の範囲に収める」処理を Clamp メソッドに切り出しています。

OrderQuantity.cs:

OrderQuantity.cs
namespace Ch10_ClassDetails;
class OrderQuantity
{
public int Quantity { get; set; }
public int Stock { get; set; }
public OrderQuantity(int quantity, int stock)
{
Quantity = Clamp(quantity, 1, 99);
Stock = Clamp(stock, 0, 9999);
}
private int Clamp(int value, int min, int max)
{
if (value < min) return min;
if (value > max) return max;
return value;
}
}

呼び出し:

OrderQuantity order = new OrderQuantity(150, -5);
Console.WriteLine($"数量:{order.Quantity}、在庫:{order.Stock}");

実行結果:

数量:99、在庫:0

ポイント:

  • 同じ「範囲補正」ロジックを 1 か所にまとめて使い回す ので、書き間違いを減らせる
  • Clampprivate を付けて、クラスの内部でだけ使う道具 であることを表す(private の詳しい意味は 10-5「アクセス修飾子」で学びます)
  • コンストラクターが「入口チェック」、private メソッドが「内部の道具」というように、役割分担ができる

補足:引数 1 つだけのシンプルなコンストラクター

コンストラクターは、プロパティが 1 つだけのシンプルなクラスでも有用です。

class TrainingDay
{
public int DayNumber { get; set; }
public TrainingDay(int dayNumber)
{
DayNumber = dayNumber;
}
}

new TrainingDay(3) のように、作成と同時に必要な値を 1 つだけ受け取る 形です。 引数の数は 必要なだけ で構いません(0 個・1 個・3 個・5 個など、業務の都合に合わせて)。

ここまでの流れと、次の節

10-4 で扱ったコンストラクターは、オブジェクトを 正しく作る ための道具でした。 次の 10-5 では、作った後の プロパティの読み書きをより細かく制御する 道具を見ていきます。 「10-4 = 作る側 / 10-5 = 守る側」と覚えると、章後半の全体像が掴みやすくなります。


10-5 プロパティの高度な使い方

Section titled “10-5 プロパティの高度な使い方”

この節では、プロパティを 「ただの値置き場」から「賢い窓口」に進化させる方法 を学びます。次の流れで進みます。

get / set を明示する → 値の取得・代入に処理を加える
バッキングフィールドと value → 内部の値の保管場所
読み取り専用プロパティ → 外から代入できない
アクセス修飾子 → 「どこから使えるか」を決める
private set → 読み取りは外に開き、代入はクラス内だけに閉じる
プロパティの初期化 → オブジェクト作成直後の値
カプセル化 → ここまでの道具をまとめた考え方

最後の「カプセル化」で、これらの道具がどう組み合わさるかを整理します。


自動実装プロパティのおさらい

Section titled “自動実装プロパティのおさらい”

これまで使ってきたプロパティは 自動実装プロパティ と呼ばれます。

public string EmployeeName { get; set; }

これは「値の取得(get)と代入(set)を自動で用意する」書き方です。 単に値を保持するだけなら、これで十分です。


値の取得・代入時に 処理を加えたい 場合は、getset を明示します。

次の例では、点数が 0 未満なら 0、100 超なら 100 に補正します。

TestScore.cs:

TestScore.cs
namespace Ch10_ClassDetails;
class TestScore
{
private int _score;
public int Score
{
get
{
return _score;
}
set
{
if (value < 0)
{
_score = 0;
}
else if (value > 100)
{
_score = 100;
}
else
{
_score = value;
}
}
}
}

Program.cs:

TestScore test = new TestScore();
test.Score = 120;
Console.WriteLine($"120を代入:{test.Score}");
test.Score = -10;
Console.WriteLine($"-10を代入:{test.Score}");
test.Score = 75;
Console.WriteLine($"75を代入:{test.Score}");

実行結果:

120を代入:100
-10を代入:0
75を代入:75

get/set を明示するときは、内部で値を保持する変数(バッキングフィールド)を別途用意します。 慣習として、先頭にアンダースコアを付けた小文字(_score など)を使うことが多いです。

private int _score; // ← バッキングフィールド(クラス外からは見えない)
public int Score // ← 外向きの窓口
{
get { return _score; }
set { _score = value; }
}

set の中で使う value は、プロパティに代入された値を表す特別なキーワードです。

test.Score = 120; // ← この 120 が、set の中で value になる
外から代入 → value に入る → バッキングフィールドへ保存
120 120 _score = 100(補正後)

set の使い方として、もう一つ典型的なのが 「入力をクリーンに整える」 パターンです。 次の例では、社員名を代入されたときに 前後の空白を取り除いてから バッキングフィールドに保存します。

EmployeeNameHolder.cs:

EmployeeNameHolder.cs
namespace Ch10_ClassDetails;
class EmployeeNameHolder
{
private string _employeeName;
public string EmployeeName
{
get { return _employeeName; }
set { _employeeName = value.Trim(); }
}
}

呼び出し:

EmployeeNameHolder holder = new EmployeeNameHolder();
holder.EmployeeName = " 山田二郎 ";
Console.WriteLine($"[{holder.EmployeeName}]");

実行結果:

[山田二郎]

Trim() は文字列の前後の空白を取り除く string のメソッドです。 利用者は「文字列を渡しただけ」のつもりでも、プロパティが 裏で整形してくれる ようになっています。 このように、set には「補正(TestScore の例)」だけでなく、「整形(本例)」のロジックも書けます。


set を持たない、外から代入できない プロパティも作れます。 他のプロパティから計算される値に使うと便利です。

Person.cs:

Person.cs
namespace Ch10_ClassDetails;
class Person
{
public string LastName { get; set; }
public string FirstName { get; set; }
public string FullName
{
get
{
return LastName + FirstName;
}
}
}

呼び出し:

Person person = new Person
{
LastName = "山田",
FirstName = "二郎"
};
Console.WriteLine(person.FullName);

実行結果:

山田二郎

person.FullName = "佐藤昭夫"; のような代入はエラーになります(set がないため)。

読み取り専用プロパティをもう一つ例で見てみましょう。 次の BookProgress は、総ページ数と読了ページ数から 残りページ数完了したかどうか を計算して返します。

BookProgress.cs:

BookProgress.cs
namespace Ch10_ClassDetails;
class BookProgress
{
public string Title { get; set; }
public int TotalPages { get; set; }
public int ReadPages { get; set; }
public int RemainingPages
{
get
{
return TotalPages - ReadPages;
}
}
public bool IsCompleted
{
get
{
return ReadPages >= TotalPages;
}
}
}

呼び出し:

BookProgress book = new BookProgress
{
Title = "C# 入門",
TotalPages = 300,
ReadPages = 120
};
Console.WriteLine($"{book.Title}:残り{book.RemainingPages}ページ、完了:{book.IsCompleted}");

実行結果:

C# 入門:残り180ページ、完了:False

このクラスは 2 つの読み取り専用プロパティ(RemainingPagesIsCompleted)を持ちます。 TotalPagesReadPages を変えるたびに、これらの値も連動して変わる仕組みです。 このように、読み取り専用プロパティは「他のプロパティから導き出される値」を表すのに向いています。


ここまで、プロパティやメソッドを書くときに、毎回 public を付けてきました。バッキングフィールドでは private を使ったところもあります。

public string EmployeeName { get; set; } // ← public
private int _score; // ← private

publicprivateアクセス修飾子 と呼ばれ、「そのプロパティ・メソッド・フィールドを、どこから使えるか」を決めます。

修飾子意味主な使いどころ
publicどこからでも使える外に公開するプロパティ・メソッド
private同じクラスの中だけ で使えるバッキングフィールド、内部処理用のメソッド
protected同じクラス + 派生クラス(継承先)から使える第 13 章「継承」の周辺で出てくる(本書では基本使わない)
internal同じプロジェクト内 からだけ使えるライブラリと業務コードを分ける現場で使う

本研修では、まず publicprivate の 2 つを使いこなせるようになれば十分 です。protectedinternal は、配属後に現場のコードで出会ったときに調べれば追いつけます。

ここまでの章で public ばかり書いてきたのは、「外から使うプロパティ・メソッドだから」という理由がありました。本章で新しく登場する private は、「外から触らせたくない内部の道具」を表します。

補足:アクセス修飾子を省略するとどうなる?

クラスのメンバー(プロパティ・メソッド・フィールド)で修飾子を省略すると、自動的に private 扱いになります。class 自体の修飾子を省略した場合は internal 扱いです。

ただし「省略 = private のつもり」だと 読み手に伝わりにくい ため、本書ではプロパティ・メソッドには 必ず修飾子を明示 します。

次の private set は、この publicprivateプロパティの読み書き(get と set)で別々に指定する 仕組みです。


private set を使うと、外からは読み取りだけ・クラスの内部からは変更可能 なプロパティを作れます。

Employee.cs(改造版):

Employee.cs
namespace Ch10_ClassDetails;
class Employee
{
public int EmployeeId { get; private set; }
public string EmployeeName { get; private set; }
public string DepartmentName { get; private set; }
public Employee(int employeeId, string employeeName, string departmentName)
{
EmployeeId = employeeId;
EmployeeName = employeeName;
DepartmentName = departmentName;
}
public void ChangeDepartment(string newDepartmentName)
{
DepartmentName = newDepartmentName;
}
}

呼び出し:

Employee employee = new Employee(1001, "山田二郎", "総務");
Console.WriteLine(employee.DepartmentName);
employee.ChangeDepartment("開発");
Console.WriteLine(employee.DepartmentName);
// employee.EmployeeName = "佐藤昭夫"; ← エラー(private set のため代入不可)

実行結果:

総務
開発

ポイント:

  • EmployeeId などは外から 参照はできる(Console.WriteLine(employee.EmployeeId) は OK)
  • 外から直接 代入はできない(employee.EmployeeId = 9999; はエラー)
  • 値を変更したいときは、用意されたメソッド(ChangeDepartment など)を経由する

このように、変更方法を限定すると、意図しない変更 を防ぎやすくなります。


プロパティに 初期値 を設定しておくこともできます。

class TrainingStatus
{
public string EmployeeName { get; set; } = "未設定";
public int ProgressRate { get; set; } = 0;
public bool IsCompleted { get; set; } = false;
}

オブジェクトを new した直後から、これらの初期値が入った状態になります。 コンストラクターに書かなくても初期値を持たせられるので、シンプルになります。


ここまでに学んだ次のような工夫は、オブジェクト指向プログラミングで カプセル化 と呼ばれる考え方そのものです。

工夫効果
private でバッキングフィールドを隠す中身に直接触らせない
set で値の範囲を補正する不正な値が入らない
private set で外からの代入を制限する勝手に書き換えられない
変更用のメソッドを用意する変更経路がはっきりする
コンストラクターで必要な値を必ず受け取る中途半端な状態のオブジェクトを作らせない

カプセル化が目指す 3 つのこと

Section titled “カプセル化が目指す 3 つのこと”

カプセル化を一言でいうと、「オブジェクトの内部状態を守り、必要な操作だけを外に公開する」考え方です。 やや細かく見ると、次の 3 つに分けて考えられます。

目的何をするか本章で使った道具
① 状態を隠す内部のフィールドを外から見せないprivate フィールド
② 操作を限定する値を変える方法を、用意したメソッド経由に絞るprivate set + 専用メソッド(例:ChangeDepartmentDeposit / Withdraw)
③ 不正な状態を作らせない値の範囲・初期化を強制するset での補正、引数付きコンストラクター

業務アプリは複数人で開発し、何年も使われます。誰かが「便利だから」と銀行口座の Balance プロパティを account.Balance = 100000; と直接書き換えてしまうと、取引履歴と残高がずれてしまい、原因の追跡に丸一日かかる、ということが起こります。

カプセル化を効かせておくと、「残高が変わった瞬間 = 入出金メソッドが呼ばれた瞬間」 に絞られるため、後から問題を追いかけやすくなります。書く時は少し手間が増えますが、読む時・直す時の手間を大きく減らす のがカプセル化の狙いです。

カプセル化は OOP の基本姿勢なので、本書のこの先でも繰り返し出てきます。

カプセル化の出番
第 13 章(継承)親クラスのプロパティを子クラスから安全に変更するために、private set + 専用メソッドを使う
第 14 章(インターフェイス)公開する操作だけを interface で約束し、内部実装は隠す
第 23〜25 章(Windows フォーム社員管理)EmployeeRepository クラスで DB アクセスをまとめ、画面側からは SQL を見せない
第 27〜30 章(Web 社員管理)同じく Repository パターンで内部を隠す

本章では、まず次のように覚えておきましょう。

外から直接変更させたくない値は private set で制限する
変更が必要な場合は、メソッドを通して変更させる
不正な値が入らないようにプロパティで確認する
必要な値はコンストラクターで必ず受け取る

つまずき原因対応
return の型が合わない戻り値の型と返す値の型が違うメソッド名の前の型を確認する
オーバーロードできない引数が同じで戻り値だけ違う引数の数や型を変える
省略可能な引数でエラー省略可能な引数を前に置いている省略可能な引数は後ろに書く
コンストラクターに戻り値の型を書いてしまう通常メソッドと混同コンストラクターには戻り値の型を書かない
コンストラクター名を間違えるクラス名と一致していないコンストラクター名はクラス名と同じ
new Employee() が使えない引数なしコンストラクターが定義されていない必要なら引数なしコンストラクターを追加
value の意味が分からないset の仕組みに慣れていない「代入された値が value に入る」と覚える
private set のプロパティに代入できない外部からの変更が制限されているコンストラクターや専用メソッドで変更する
読み取り専用プロパティに代入しようとするset がない計算結果や参照専用の値として使う
バッキングフィールドと無限ループget { return Score; } のように同名プロパティを呼んでしまうバッキングフィールド(_score)を返す
プロパティ・メソッドを外から呼べないアクセス修飾子を書き忘れて自動で private 扱いになっている外に公開するメンバーには 必ず public を明示 する
private フィールドを外から使おうとするクラスの外からは見えない外から使うなら public プロパティ経由にする

  • intstringbool・自作クラスを戻り値にしたメソッドを書ける
  • メソッドのオーバーロードを書ける
  • 省略可能な引数を持つメソッドを書ける
  • 名前付き引数で呼び出せる
  • 引数付きコンストラクターを書ける
  • コンストラクターをオーバーロードできる
  • this(...) で別のコンストラクターを呼び出せる
  • get / set を明示してプロパティを書ける
  • value の役割を説明できる
  • 読み取り専用プロパティを書ける
  • private set を使える
  • プロパティに初期値を設定できる
  • アクセス修飾子(public / private)の意味を説明し、使い分けられる
  • カプセル化が目指す 3 つのこと(状態を隠す / 操作を限定する / 不正な状態を作らせない)を説明できる

研修の進め方によっては、隣の人またはチーム内で説明確認を行います。

次の内容を、自分の言葉で説明してください。

  1. メソッドのオーバーロードとは何ですか。
  2. 省略可能な引数はどのようなときに便利ですか。
  3. コンストラクターはいつ呼び出されますか。
  4. 引数付きコンストラクターを使うメリットは何ですか。
  5. getset は何をするものですか。
  6. value は何を表しますか。
  7. private set はどのようなときに使いますか。
  8. publicprivate の違いを、自分の言葉で説明してください。
  9. カプセル化が目指す 3 つのこと(状態を隠す / 操作を限定する / 不正な状態を作らせない)を、覚えている範囲で挙げてください。

説明するときは、完全な答えでなくても構いません。 自分の言葉で説明しようとすることが大切です。


この章の演習課題に取り組みます。

本章では タイマー方式 を試験導入します。次の 3 段階で進めてください。

段階時間内容
① 準備10 分(目安)上の「ペア確認」と、これから取り組む課題(仕様)の読み込み。ペアや講師に質問してよい
② ソロ作業40 分(タイマーで計測)一人で課題に取り組む。タイマーが鳴ったら、完成・未完成にかかわらず作業を止めて提出する
③ チーム時間講師が指定する発表開始時刻までチーム内でコードレビューを行い、発表者を決める。実装の続行も可。時間配分はチームで管理する

第 10 章は コンストラクター・プロパティの高度な使い方 を扱う章で、覚えることが多めです。ソロ作業は 40 分 をとっています。準備フェーズの終わりに講師が号令をかけ、そこからタイマーを開始します。 評価対象はタイマー時点で提出されたコードです(タイマー後に書き足した分は評価には含まれません)。 発表開始時刻は厳守 です。チーム時間中も、その時刻が来たら全員手を止めて発表に移ります。

演習の進め方の詳細は、付録A「演習の進め方」 を参照してください。


課題はソリューション Kadai10 の中に作成してください。 課題ごとに別のプロジェクトを作成 し、指定されたプロジェクト名を使います。

課題必須/発展プロジェクト名作成する主なファイル
課題 10-1必須Kd10_01_EmployeeConstructorProgram.csEmployee.cs
課題 10-2必須Kd10_02_SearchOverloadProgram.csEmployeeSearchService.cs
課題 10-3必須Kd10_03_ScoreValidationProgram.csTestScore.cs
課題 10-4発展Kd10_04_GreetingServiceProgram.csGreetingService.cs
課題 10-5発展Kd10_05_BankAccountProgram.csBankAccount.cs
課題 10-6発展Kd10_06_OrderItemProgram.csOrderItem.cs

フォルダ構成は次のようになります。

Kadai10/ ← 課題用ソリューションフォルダ
Kadai10.sln
Kd10_01_EmployeeConstructor/
Kd10_02_SearchOverload/
Kd10_03_ScoreValidation/
Kd10_04_GreetingService/
Kd10_05_BankAccount/
Kd10_06_OrderItem/

補足:ソリューションに複数のプロジェクトを追加する方法

最初の課題で Kadai10 ソリューションと Kd10_01_EmployeeConstructor プロジェクトを同時に作成します。

2 つ目以降の課題は、ソリューションエクスプローラーで Kadai10 を右クリックし、追加新しいプロジェクト から追加します。


以下は、本章のすべての課題に共通する作業です。各課題の本文には繰り返し書きません。

作業内容参照
プロジェクト作成時の設定最上位レベルのステートメントを使用しない」にチェック第 1 章 1-1
csproj の編集<Nullable>disable</Nullable> に変更第 1 章 1-1
namespace の書き方ファイルスコープ形式(namespace XXX;)で書く第 7 章 冒頭
クラスファイルの追加ソリューションエクスプローラーでプロジェクトを右クリック → 追加クラス第 7 章 7-7
ファイルを保存して実行Ctrl + S で保存 → F5 で実行第 1 章 1-2

特に 2 つ目以降のプロジェクト(Kd10_02_SearchOverload など)も、新規追加するたびに csproj の Nullable を disable に変更する 必要があります。

クラスファイルを自動生成すると、ブロック形式の namespace プロジェクト名 { ... } で作られます(例:課題 10-1 なら namespace Kd10_01_EmployeeConstructor { ... })。本章でもファイルスコープ形式に統一するため、生成後に namespace Kd10_01_EmployeeConstructor; のように ; 形式に書き換えてください。同じプロジェクト内の Program.cs と他のクラスファイルの namespace は揃えます。

提出ルール(タイマー方式)

  • 準備フェーズの後、講師の号令で 40 分のタイマー をスタートします
  • タイマーが鳴ったら、完成・未完成にかかわらず手を止め、その場で git addgit commitgit push を行います
  • これがこの演習の 唯一の提出 です。タイマー後も実装を続けて構いませんが、書き足した分は評価対象には含まれません

コミットメッセージの形式:

Chapter10 タイマー提出: <どの課題まで完成> / <詰まったポイント>

例:

  • Chapter10 タイマー提出: 10-1〜10-2完成、10-3は途中 / set の中の value の使い方で詰まっている
  • Chapter10 タイマー提出: 10-1〜10-3完成、発展未着手 / 特になし
  • Chapter10 タイマー提出: 10-1完成、10-2の途中 / コンストラクターの引数の順番でエラーが取れない

「どこまでできたか」「詰まったポイント」は短くて構いません。順調なときも「特になし」と明示 してください(順調さの証拠になります)。

提出方法:Git が使えないときはサーバへコピー

Git の状態によっては、講師から「今回は push ではなくサーバへのフォルダコピーで提出」と指示が出ることがあります。その場合は、push の代わりに Kadai10 フォルダをサーバの所定の場所へコピーして提出してください(コピー手順は別途案内済みのとおり)。

このとき コミットメッセージが残せない ため、代わりに 提出メモ.txt というテキストファイルを提出先に作成します。コピーが終わってから、次の手順で作成してください。

  1. Kadai10 フォルダをコピーした、サーバ上の自分の名前のフォルダをエクスプローラーで開く
  2. 何もないところで右クリック → 新規作成 → テキスト ドキュメント を選ぶ
  3. ファイル名を 提出メモ.txt に変更する
  4. ダブルクリックで開き、次の内容を書いて保存する
どこまで完成: 10-1〜10-3完成、発展未着手
詰まったポイント: 特になし

書く内容は、コミットメッセージに書くはずだった「どこまで完成したか」「詰まったポイント」と同じです。順調なときも「詰まったポイント: 特になし」と明示 してください。

タイマー後のチーム時間の使い方

タイマー後、講師が指定する 発表開始時刻 までがチーム時間です。チーム内で次の 3 つを自由に管理してください。

  • コードレビュー:他のメンバーの commit を読んで、気づいたことを共有する
  • 発表者の選出:発表開始時刻に、チームから 1 人が要点を発表できるよう、誰が話すかを決めておく
  • 実装の続行(任意):途中だった課題を続けても構いません(提出後の追加分は評価対象外ですが、理解を深める意義はあります)

どの順番で進めるか、何分ずつ使うかはチームの判断です。ただし 発表開始時刻は厳守 です。その時刻までにレビューと発表者選出を必ず終わらせてください。


まずは、全員が必須課題に取り組んでください。


課題 10-1 引数付きコンストラクター

Section titled “課題 10-1 引数付きコンストラクター”

Employee クラスを別ファイル(Employee.cs)に作成し、引数付きコンストラクターで初期値を設定するプログラムを作ってください。

Employee クラスのプロパティ:

プロパティ名意味
EmployeeIdint社員番号
EmployeeNamestring氏名
DepartmentNamestring部署

Main メソッドの処理:

  • new Employee(1001, "山田二郎", "総務") でオブジェクトを作成する
  • GetDisplayText() メソッド(社員情報を "1001:山田二郎(総務)" の形式で返す)を呼び出して結果を表示する

実行結果例:

1001:山田二郎(総務)

条件:

  • 引数付きコンストラクターを定義する
  • GetDisplayText メソッドの戻り値は string
  • オブジェクト初期化子(new Employee { ... })は使わない

課題 10-2 メソッドのオーバーロード

Section titled “課題 10-2 メソッドのオーバーロード”

EmployeeSearchService クラスを作成し、社員番号と氏名のどちらでも検索できる Search メソッドをオーバーロードで定義してください。

メソッド引数表示内容
Search(int)社員番号"社員番号 {番号} で検索します。"
Search(string)氏名"氏名 {氏名} で検索します。"

Main メソッドの処理:

  • service.Search(1001);service.Search("山田二郎"); の両方を呼び出す

実行結果例:

社員番号 1001 で検索します。
氏名 山田二郎 で検索します。

条件:

  • 同じ名前 Search で 2 つのメソッドを定義する
  • 引数の を変えてオーバーロードする

課題 10-3 プロパティで値を補正する

Section titled “課題 10-3 プロパティで値を補正する”

TestScore クラスを作成し、Score プロパティに 0〜100 の範囲外の値が入ったときに自動で補正されるようにしてください。

仕様:

代入値保存される値
120100
-100
7575

Main メソッドの処理:

  • TestScore オブジェクトを 1 つ作成
  • 120-1075 をそれぞれ代入し、その後 Score プロパティを表示する

実行結果例:

120を代入した結果:100
-10を代入した結果:0
75を代入した結果:75

条件:

  • バッキングフィールド private int _score; を使う
  • getset を明示して書く
  • set の中で value を使う

必須課題が終わった人は、発展課題に取り組んでください。 発展課題からは、仕様だけが提示されます。実装方法は自分で考えてください。


課題 10-4 省略可能な引数と名前付き引数

Section titled “課題 10-4 省略可能な引数と名前付き引数”

以下の仕様で GreetingService クラスを実装してください。

クラス仕様

  • クラス名:GreetingService
  • ファイル名:GreetingService.cs
  • メソッド:
    • CreateMessage(string employeeName, string title = "さん", bool exclaim = false):
      • 戻り値:string
      • exclaimfalse のとき:"{employeeName}{title}、こんにちは。"
      • exclaimtrue のとき:"{employeeName}{title}、こんにちは!!"

Main メソッド仕様

次の 3 通りを呼び出して、結果を表示する。

呼び出し期待する表示
CreateMessage("山田二郎")山田二郎さん、こんにちは。
CreateMessage("田中浩介", "先生")田中浩介先生、こんにちは。
CreateMessage("佐藤昭夫", exclaim: true)佐藤昭夫さん、こんにちは!!

条件:

  • 既定値を持つ引数を使う
  • 3 番目の呼び出しでは 名前付き引数 を使う

課題 10-5 private set で守られた BankAccount クラス

Section titled “課題 10-5 private set で守られた BankAccount クラス”

第 7 章発展課題 7-4 で作成した BankAccount クラスを、private set を使って 「残高は外から直接書き換えられない、入出金メソッドを通してしか変更できない」 ようにしてください。

第 7 章版との違い:

項目第 7 章 7-4(復習)本課題(10-5)
プロパティの公開public ... { get; set; }(外から代入可能)public ... { get; private set; }(外から代入不可)
初期化new してからプロパティに代入引数付きコンストラクター で初期化
残高変更外から直接代入もメソッド経由も可能Deposit / Withdraw メソッドを通すしかない

クラス仕様

  • クラス名:BankAccount
  • ファイル名:BankAccount.cs
  • プロパティ(すべて public ... { get; private set; }):
    • OwnerName (string):口座名義
    • Balance (int):残高
  • コンストラクター:
    • BankAccount(string ownerName, int initialBalance):名義と初期残高を受け取って初期化する
  • メソッド:
    • Deposit(int amount):amountBalance に加算する(戻り値 void)
    • Withdraw(int amount):amountBalance から減算する(戻り値 void)
    • PrintBalance():"名義:{OwnerName} 残高:{Balance}円" を表示する(戻り値 void)

Main メソッド仕様

  • new BankAccount("山田二郎", 0) で口座を作成する
  • PrintBalance() で残高を表示
  • Deposit(50000) で入金 → PrintBalance() で残高を表示
  • Withdraw(20000) で出金 → PrintBalance() で残高を表示

実行結果例:

名義:山田二郎 残高:0円
名義:山田二郎 残高:50000円
名義:山田二郎 残高:30000円

確認事項:

  • Main メソッドから account.Balance = 100000; のように直接代入しようとするとコンパイルエラーになることを確認する(確認後、その行は削除またはコメントアウトする)
  • 残高を変更するには Deposit / Withdraw メソッドを呼ぶしかないことを実感する

補足:この設計の意味

銀行口座の残高を、外部のコードから自由に書き換えられると、取引履歴と残高がずれてしまいます。private set + 入出金メソッドという形にすると、残高の変更経路を入出金に限定 できます。これがカプセル化の典型例です。


課題 10-6 OrderItem クラス(統合課題)

Section titled “課題 10-6 OrderItem クラス(統合課題)”

注文商品を表す OrderItem クラスを実装してください。 この課題は、この章で学んだ「引数付きコンストラクター」「値の補正」「読み取り専用プロパティ」を組み合わせる統合課題です。

クラス仕様

  • クラス名:OrderItem
  • プロパティ:
    • ProductName (string):get; private set;
    • UnitPrice (int):get; private set;(0 未満は 0 に補正)
    • Quantity (int):get; private set;(1 未満は 1 に補正)
    • Amount (int):読み取り専用プロパティUnitPrice * Quantity を返す
  • コンストラクター:
    • OrderItem(string productName, int unitPrice, int quantity)
    • 値の補正はコンストラクターまたは set のどちらで行ってもよい

Main メソッド仕様

次の OrderItem を作成し、内容を表示する。

OrderItem item = new OrderItem("ノート", 180, 5);

実行結果例:

商品名:ノート
単価:180円
数量:5個
金額:900円

不正値で作成した場合(例:new OrderItem("ノート", -100, 0))、補正された値が表示されることも確認してください。


  • プログラムを Visual Studio から実行できる
  • 戻り値のあるメソッドを作成できている
  • return する値の型が戻り値の型と合っている
  • メソッドのオーバーロードを使えている
  • 省略可能な引数を使えている(発展)
  • 引数付きコンストラクターを書けている
  • コンストラクター名がクラス名と一致している
  • コンストラクターに戻り値の型を書いていない
  • get / set を明示して書けている
  • value の意味を理解している
  • private set を使えている(発展)
  • 読み取り専用プロパティを使えている(発展)
  • クラスを別ファイルに分けて書けている
  • インデントが整っている
  • 課題を提出した(Git の commitpush、または講師指示があれば Kadai10 フォルダをサーバへコピーし、提出先フォルダに 提出メモ.txt を作成)

タイマーが鳴ったら、第 10 章の課題プロジェクト群(Kadai10 ソリューション)をその場で Git に提出します。

Terminal window
git status
git add .
git commit -m "Chapter10 タイマー提出: <どこまで完成> / <詰まったポイント>"
git push

実行例:

Terminal window
git commit -m "Chapter10 タイマー提出: 10-1〜10-2完成、10-3は途中 / set の中の value の使い方で詰まった"

Git の詳しい操作は、付録 C「Git のインストールと提出ルール」 を参照してください。

コミットメッセージの形式は、本章冒頭「演習課題 > 提出ルール(タイマー方式)」を参照してください。

サーバへのコピーで提出する場合

講師から指示があった場合は、push の代わりに Kadai10 フォルダをサーバへコピーして提出します。コピー後、提出先(サーバ上の自分の名前のフォルダ)をエクスプローラーで開き、右クリック → 新規作成 → テキスト ドキュメント で 提出メモ.txt を作って「どこまで完成」「詰まったポイント」を書いてください。詳しくは本章冒頭「演習課題 > 提出方法:Git が使えないときはサーバへコピー」を参照してください。


この章では、クラスを使いこなすための機能を学習しました。

  • メソッドは intstringbool・自作クラスなど、さまざまな型を返せる
  • 同じ名前で引数の異なるメソッドを複数定義できる(オーバーロード)
  • 省略可能な引数を使うと、引数を省略してメソッドを呼び出せる
  • 名前付き引数(引数名: 値)で読みやすく呼び出せる
  • コンストラクターは、オブジェクト作成時に自動的に呼び出される
  • コンストラクターは初期化や必要な値の受け取りに使う
  • コンストラクターもオーバーロードできる、this(...) で別のコンストラクターを呼べる
  • getset を明示すると、プロパティに処理を加えられる
  • set の中の value は、代入された値を表す
  • 読み取り専用プロパティ(set なし)で、外からの代入を禁止できる
  • private set で、外からの直接代入を禁じつつクラス内では変更できるようにできる
  • プロパティに初期値を直接書ける
  • アクセス修飾子は、まず public(どこからでも)/ private(同じクラス内だけ)の 2 つを使い分ければよい(protected / internal は配属後に出会ったときに調べれば追いつける)
  • これらの工夫は カプセル化 という考え方そのもので、目指すのは「① 状態を隠す」「② 操作を限定する」「③ 不正な状態を作らせない」の 3 つ。第 13 章以降の継承・インターフェイス・Repository パターンでも繰り返し使う

次章では、値型と参照型 を学習します。

これまでに intboolstring・配列・クラスなど、さまざまな型を使ってきました。 次章では、これらの型が メモリ上でどのように扱われるか に注目し、値型・参照型・構造体・列挙型・null について整理します。

クラスを「中身まで複製したい」「同じ実体を共有したい」といったときに重要になる知識です。