第14章 インターフェイス
この章の目的
Section titled “この章の目的”この章では、オブジェクト指向プログラミングで重要な インターフェイス を学習します。
第13章では、継承とポリモーフィズムを学習しました。
継承では、親クラスに共通部分をまとめ、子クラスがそれを受け継ぎました。
abstract class EmployeeBase{ public abstract int GetPaymentAmount();}class RegularEmployee : EmployeeBase{ public override int GetPaymentAmount() { return MonthlySalary; }}インターフェイスも、ポリモーフィズムに関係する仕組みです。
ただし、インターフェイスは、親クラスのように共通のデータを持つというよりも、そのクラスが持つべき機能の約束を表します。
たとえば、次のような約束を作ることができます。
印刷できる保存できる検索できる支給額を計算できる一覧を取得できるC#では、このような「できること」をインターフェイスとして定義できます。
この章では、次のように考えていきます。
インターフェイス → クラスに対して「このメソッドを持っていてください」と約束するもの
クラス → インターフェイスで決められたメソッドを実装するものこの章でできるようになること
Section titled “この章でできるようになること”この章を終えると、次のことができるようになります。
- インターフェイスとは何かをおおまかに説明できる
- インターフェイスは「機能の約束」であることを説明できる
interfaceを使ってインターフェイスを定義できる- クラスでインターフェイスを実装できる
- インターフェイスにメソッドを定義できる
- インターフェイスにプロパティを定義できる
- インターフェイス型の変数に、実装クラスのオブジェクトを代入できる
List<インターフェイス>で複数のクラスをまとめて扱える- 抽象クラスとインターフェイスの違いをおおまかに説明できる
- WebアプリやDB接続でよく出てくる
ServiceやRepositoryの考え方に少し慣れる
本章で使用する環境
Section titled “本章で使用する環境”| 項目 | 内容 |
|---|---|
| 開発環境 | Visual Studio 2022 |
| プロジェクト種類 | コンソール アプリ |
| 対象フレームワーク | .NET 8 |
| プロジェクト名 | Chapter14_Interface |
作業前チェック
Section titled “作業前チェック”作業を始める前に、次の内容を確認してください。
- クラスを作成できる
- プロパティを定義できる
- メソッドを定義できる
- 継承の基本を説明できる
- 抽象クラスの基本を説明できる
-
List<T>を使える -
foreach文を使える - 第13章の内容をGitに提出済みである
14-1 インターフェイスとは?
Section titled “14-1 インターフェイスとは?”インターフェイスは「約束」
Section titled “インターフェイスは「約束」”インターフェイスは、クラスが持つべき機能を決めるための仕組みです。
たとえば、「印刷できる」という機能を考えます。
印刷できるもの → Print メソッドを持っているこの約束をインターフェイスとして表すと、次のようになります。
interface IPrintable{ void Print();}IPrintable は、「印刷できるもの」を表すインターフェイスです。
このインターフェイスを実装するクラスは、必ず Print メソッドを持つ必要があります。
インターフェイス名の慣習
Section titled “インターフェイス名の慣習”C#では、インターフェイス名の先頭に I を付けることが多いです。
例:
IPrintableISearchableIPayableIEmployeeRepositoryI は Interface の頭文字です。
必ずではありませんが、現場のC#コードでは非常によく使われる命名です。
インターフェイスを実装する
Section titled “インターフェイスを実装する”Employee クラスで IPrintable を実装してみます。
using System;
class Program{ static void Main() { Employee employee = new Employee { EmployeeId = 1001, EmployeeName = "山田太郎", DepartmentName = "営業部" };
employee.Print(); }}
interface IPrintable{ void Print();}
class Employee : IPrintable{ public int EmployeeId { get; set; } public string EmployeeName { get; set; } = ""; public string DepartmentName { get; set; } = "";
public void Print() { Console.WriteLine($"社員ID:{EmployeeId}"); Console.WriteLine($"氏名:{EmployeeName}"); Console.WriteLine($"部署:{DepartmentName}"); }}実行結果:
社員ID:1001氏名:山田太郎部署:営業部次の部分に注目してください。
class Employee : IPrintableこれは、Employee クラスが IPrintable インターフェイスを実装していることを表します。
インターフェイスを実装したクラスは、インターフェイスで定義されたメソッドを必ず持つ必要があります。
public void Print(){ Console.WriteLine($"社員ID:{EmployeeId}"); Console.WriteLine($"氏名:{EmployeeName}"); Console.WriteLine($"部署:{DepartmentName}");}もし Print メソッドを書かなければ、コンパイルエラーになります。
インターフェイス自体には処理を書かない
Section titled “インターフェイス自体には処理を書かない”この章では、インターフェイスは次のように書くものとして扱います。
interface IPrintable{ void Print();}Print メソッドの中身は書きません。
処理の中身は、インターフェイスを実装するクラス側に書きます。
class Employee : IPrintable{ public void Print() { Console.WriteLine("社員情報を表示します。"); }}補足
新しいC#では、インターフェイスに既定の実装を書ける機能もあります。 ただし、初学者向けの本研修では、まず「インターフェイスは約束だけを書くもの」として理解します。
14-2 インターフェイス型として扱う
Section titled “14-2 インターフェイス型として扱う”インターフェイス型の変数
Section titled “インターフェイス型の変数”インターフェイスを実装したクラスのオブジェクトは、インターフェイス型の変数に代入できます。
IPrintable printable = new Employee{ EmployeeId = 1001, EmployeeName = "山田太郎", DepartmentName = "営業部"};この場合、printable は IPrintable 型として扱われます。
つまり、IPrintable に定義されている Print メソッドを呼び出せます。
インターフェイス型でPrintを呼び出す
Section titled “インターフェイス型でPrintを呼び出す”using System;
class Program{ static void Main() { IPrintable printable = new Employee { EmployeeId = 1001, EmployeeName = "山田太郎", DepartmentName = "営業部" };
printable.Print(); }}
interface IPrintable{ void Print();}
class Employee : IPrintable{ public int EmployeeId { get; set; } public string EmployeeName { get; set; } = ""; public string DepartmentName { get; set; } = "";
public void Print() { Console.WriteLine($"社員ID:{EmployeeId}"); Console.WriteLine($"氏名:{EmployeeName}"); Console.WriteLine($"部署:{DepartmentName}"); }}実行結果:
社員ID:1001氏名:山田太郎部署:営業部インターフェイス型では約束された機能だけ使える
Section titled “インターフェイス型では約束された機能だけ使える”次のコードでは、printable は IPrintable 型です。
IPrintable printable = new Employee{ EmployeeId = 1001, EmployeeName = "山田太郎", DepartmentName = "営業部"};この場合、Print メソッドは呼び出せます。
printable.Print();しかし、次のように EmployeeName を直接参照しようとするとエラーになります。
Console.WriteLine(printable.EmployeeName);Employee クラスには EmployeeName がありますが、IPrintable インターフェイスには EmployeeName が定義されていないからです。
このように、インターフェイス型として扱う場合、そのインターフェイスで約束されたメンバーだけを利用できます。
インターフェイスにプロパティを定義する
Section titled “インターフェイスにプロパティを定義する”インターフェイスには、メソッドだけでなくプロパティも定義できます。
interface IPrintable{ string Title { get; }
void Print();}この場合、実装クラスは Title プロパティと Print メソッドを持つ必要があります。
using System;
class Program{ static void Main() { IPrintable report = new SalesReport();
Console.WriteLine(report.Title); report.Print(); }}
interface IPrintable{ string Title { get; }
void Print();}
class SalesReport : IPrintable{ public string Title { get { return "売上レポート"; } }
public void Print() { Console.WriteLine("売上レポートを出力します。"); }}実行結果:
売上レポート売上レポートを出力します。14-3 複数のクラスを同じインターフェイスで扱う
Section titled “14-3 複数のクラスを同じインターフェイスで扱う”別々のクラスに同じ機能を持たせる
Section titled “別々のクラスに同じ機能を持たせる”インターフェイスの大きなメリットは、別々のクラスを同じ機能でまとめて扱えることです。
たとえば、次の2つのクラスを考えます。
Employee → 社員情報を印刷できる
SalesReport → 売上レポートを印刷できるこの2つは、同じ種類のクラスではありません。
しかし、どちらも「印刷できる」という機能を持っています。
そこで、どちらにも IPrintable を実装させます。
EmployeeとSalesReportにIPrintableを実装する
Section titled “EmployeeとSalesReportにIPrintableを実装する”using System;
class Program{ static void Main() { Employee employee = new Employee { EmployeeId = 1001, EmployeeName = "山田太郎", DepartmentName = "営業部" };
SalesReport report = new SalesReport { ReportDate = new DateTime(2026, 5, 18), TotalAmount = 1200000 };
employee.Print(); report.Print(); }}
interface IPrintable{ void Print();}
class Employee : IPrintable{ public int EmployeeId { get; set; } public string EmployeeName { get; set; } = ""; public string DepartmentName { get; set; } = "";
public void Print() { Console.WriteLine($"社員ID:{EmployeeId}"); Console.WriteLine($"氏名:{EmployeeName}"); Console.WriteLine($"部署:{DepartmentName}"); }}
class SalesReport : IPrintable{ public DateTime ReportDate { get; set; } public int TotalAmount { get; set; }
public void Print() { Console.WriteLine($"売上日:{ReportDate.ToString("yyyy/MM/dd")}"); Console.WriteLine($"売上合計:{TotalAmount}円"); }}実行結果:
社員ID:1001氏名:山田太郎部署:営業部売上日:2026/05/18売上合計:1200000円Listでまとめる
Section titled “Listでまとめる”Employee と SalesReport は別々のクラスですが、どちらも IPrintable を実装しています。
そのため、List<IPrintable> にまとめることができます。
using System;using System.Collections.Generic;
class Program{ static void Main() { List<IPrintable> printTargets = new List<IPrintable> { new Employee { EmployeeId = 1001, EmployeeName = "山田太郎", DepartmentName = "営業部" }, new SalesReport { ReportDate = new DateTime(2026, 5, 18), TotalAmount = 1200000 } };
foreach (IPrintable printTarget in printTargets) { printTarget.Print(); } }}
interface IPrintable{ void Print();}
class Employee : IPrintable{ public int EmployeeId { get; set; } public string EmployeeName { get; set; } = ""; public string DepartmentName { get; set; } = "";
public void Print() { Console.WriteLine($"社員ID:{EmployeeId}"); Console.WriteLine($"氏名:{EmployeeName}"); Console.WriteLine($"部署:{DepartmentName}"); }}
class SalesReport : IPrintable{ public DateTime ReportDate { get; set; } public int TotalAmount { get; set; }
public void Print() { Console.WriteLine($"売上日:{ReportDate.ToString("yyyy/MM/dd")}"); Console.WriteLine($"売上合計:{TotalAmount}円"); }}実行結果:
社員ID:1001氏名:山田太郎部署:営業部売上日:2026/05/18売上合計:1200000円foreach の中では、すべて IPrintable として扱っています。
foreach (IPrintable printTarget in printTargets){ printTarget.Print();}実際のオブジェクトが Employee なら社員情報の印刷、SalesReport なら売上レポートの印刷が実行されます。
これもポリモーフィズムの一種です。
14-4 インターフェイスとポリモーフィズム
Section titled “14-4 インターフェイスとポリモーフィズム”同じ呼び出し方で異なる処理を実行する
Section titled “同じ呼び出し方で異なる処理を実行する”第13章では、親クラス型を使ってポリモーフィズムを学びました。
List<EmployeeBase> employees = new List<EmployeeBase>{ new RegularEmployee(...), new ContractEmployee(...)};インターフェイスでも、同じようにポリモーフィズムを実現できます。
List<IPrintable> printTargets = new List<IPrintable>{ new Employee(), new SalesReport()};呼び出し側は、具体的なクラスを気にせず、インターフェイスで約束されたメソッドを呼び出します。
foreach (IPrintable printTarget in printTargets){ printTarget.Print();}IPayableを作る
Section titled “IPayableを作る”次は、支給額を計算できることを表す IPayable インターフェイスを作ります。
interface IPayable{ int GetPaymentAmount();}IPayable を実装するクラスは、必ず GetPaymentAmount メソッドを持つ必要があります。
正社員と契約社員にIPayableを実装する
Section titled “正社員と契約社員にIPayableを実装する”using System;using System.Collections.Generic;
class Program{ static void Main() { List<IPayable> payTargets = new List<IPayable> { new RegularEmployee { EmployeeName = "山田太郎", MonthlySalary = 300000 }, new ContractEmployee { EmployeeName = "佐藤花子", HourlyWage = 1800, WorkHours = 120 } };
foreach (IPayable payTarget in payTargets) { Console.WriteLine($"支給額:{payTarget.GetPaymentAmount()}円"); } }}
interface IPayable{ int GetPaymentAmount();}
class RegularEmployee : IPayable{ public string EmployeeName { get; set; } = ""; public int MonthlySalary { get; set; }
public int GetPaymentAmount() { return MonthlySalary; }}
class ContractEmployee : IPayable{ public string EmployeeName { get; set; } = ""; public int HourlyWage { get; set; } public int WorkHours { get; set; }
public int GetPaymentAmount() { return HourlyWage * WorkHours; }}実行結果:
支給額:300000円支給額:216000円RegularEmployee と ContractEmployee は、どちらも IPayable を実装しています。
そのため、List<IPayable> にまとめられます。
インターフェイス型で扱うと使える範囲が限定される
Section titled “インターフェイス型で扱うと使える範囲が限定される”先ほどのコードでは、payTarget は IPayable 型です。
foreach (IPayable payTarget in payTargets){ Console.WriteLine($"支給額:{payTarget.GetPaymentAmount()}円");}そのため、GetPaymentAmount は呼び出せます。
しかし、次のように EmployeeName を参照することはできません。
Console.WriteLine(payTarget.EmployeeName);EmployeeName は RegularEmployee や ContractEmployee にはありますが、IPayable には定義されていないからです。
インターフェイス型で扱う場合は、インターフェイスに定義された機能だけが使えることに注意してください。
14-5 複数のインターフェイスを実装する
Section titled “14-5 複数のインターフェイスを実装する”クラスは複数のインターフェイスを実装できる
Section titled “クラスは複数のインターフェイスを実装できる”C#では、1つのクラスが複数のインターフェイスを実装できます。
たとえば、社員クラスに次の2つの機能を持たせることを考えます。
印刷できる支給額を計算できるこの場合、Employee クラスは IPrintable と IPayable の両方を実装できます。
class RegularEmployee : IPrintable, IPayable{}複数のインターフェイスを実装する場合は、カンマで区切ります。
複数インターフェイスの例
Section titled “複数インターフェイスの例”using System;
class Program{ static void Main() { RegularEmployee employee = new RegularEmployee { EmployeeId = 1001, EmployeeName = "山田太郎", DepartmentName = "営業部", MonthlySalary = 300000 };
employee.Print();
int paymentAmount = employee.GetPaymentAmount(); Console.WriteLine($"支給額:{paymentAmount}円"); }}
interface IPrintable{ void Print();}
interface IPayable{ int GetPaymentAmount();}
class RegularEmployee : IPrintable, IPayable{ public int EmployeeId { get; set; } public string EmployeeName { get; set; } = ""; public string DepartmentName { get; set; } = ""; public int MonthlySalary { get; set; }
public void Print() { Console.WriteLine($"社員ID:{EmployeeId}"); Console.WriteLine($"氏名:{EmployeeName}"); Console.WriteLine($"部署:{DepartmentName}"); }
public int GetPaymentAmount() { return MonthlySalary; }}実行結果:
社員ID:1001氏名:山田太郎部署:営業部支給額:300000円継承とインターフェイスを組み合わせる
Section titled “継承とインターフェイスを組み合わせる”C#では、クラスの継承は基本的に1つだけです。
class RegularEmployee : EmployeeBase{}しかし、インターフェイスは複数実装できます。
class RegularEmployee : EmployeeBase, IPrintable, IPayable{}この場合、最初に親クラスを書き、その後にインターフェイスを書きます。
class 子クラス : 親クラス, インターフェイス1, インターフェイス2{}この章では、まず次のように覚えておきましょう。
クラスの継承 → 基本的に1つ
インターフェイスの実装 → 複数可能14-6 抽象クラスとインターフェイスの違い
Section titled “14-6 抽象クラスとインターフェイスの違い”どちらも共通の型として扱える
Section titled “どちらも共通の型として扱える”抽象クラスとインターフェイスは、どちらもポリモーフィズムに使えます。
抽象クラスの例:
abstract class EmployeeBase{ public abstract int GetPaymentAmount();}インターフェイスの例:
interface IPayable{ int GetPaymentAmount();}どちらも、共通のメソッドを呼び出すために使えます。
抽象クラスは「共通の土台」
Section titled “抽象クラスは「共通の土台」”抽象クラスは、共通のプロパティや処理を持たせたい場合に向いています。
abstract class EmployeeBase{ public int EmployeeId { get; private set; } public string EmployeeName { get; private set; }
public EmployeeBase(int employeeId, string employeeName) { EmployeeId = employeeId; EmployeeName = employeeName; }
public abstract int GetPaymentAmount();}このように、社員IDや氏名のような共通情報を持たせられます。
インターフェイスは「機能の約束」
Section titled “インターフェイスは「機能の約束」”インターフェイスは、共通のデータというよりも、持っている機能を表すのに向いています。
interface IPrintable{ void Print();}IPrintable は、「印刷できる」という機能を表しています。
社員でも、レポートでも、請求書でも、「印刷できる」なら IPrintable を実装できます。
| 観点 | 抽象クラス | インターフェイス |
|---|---|---|
| 主な役割 | 共通の土台 | 機能の約束 |
| キーワード | abstract class | interface |
| 継承・実装 | 1つのクラスのみ継承 | 複数実装できる |
| 共通プロパティ | 持たせやすい | 約束として定義できる |
| 共通処理 | 持たせやすい | 本研修では処理は書かない |
| 向いている例 | 社員の共通情報 | 印刷できる、保存できる、検索できる |
どちらを使うべきか
Section titled “どちらを使うべきか”初学者の段階では、無理に使い分けを完全に理解する必要はありません。
この章では、次のように考えてください。
共通のデータや処理をまとめたい → 抽象クラスが候補
その機能を持っていることを約束したい → インターフェイスが候補現場のコードでは、サービスやリポジトリの設計でインターフェイスが使われることがあります。
14-7 ServiceとRepositoryのイメージ
Section titled “14-7 ServiceとRepositoryのイメージ”後のWebアプリ・DB接続につながる考え方
Section titled “後のWebアプリ・DB接続につながる考え方”後の章では、Oracle Databaseから社員情報を取得します。
そのとき、次のようなクラスが登場する可能性があります。
EmployeeEmployeeServiceEmployeeRepositoryEmployeeDao現場のC#コードでは、これらに対応するインターフェイスが用意されることがあります。
IEmployeeServiceIEmployeeRepositoryこの章では、まだ本格的なDB接続は行いません。
ただし、インターフェイスがどのような場面で使われるのか、簡単なイメージを確認します。
IEmployeeRepositoryを作る
Section titled “IEmployeeRepositoryを作る”IEmployeeRepository は、社員データを取得する機能の約束を表すインターフェイスです。
interface IEmployeeRepository{ List<Employee> GetAll(); Employee? FindById(int employeeId);}このインターフェイスを実装するクラスは、次の2つのメソッドを持つ必要があります。
GetAll → 全社員を取得する
FindById → 社員IDで1件検索するサンプルデータ用のRepository
Section titled “サンプルデータ用のRepository”まだDBには接続せず、サンプルデータを返すクラスを作ります。
using System;using System.Collections.Generic;using System.Linq;
class Program{ static void Main() { IEmployeeRepository repository = new SampleEmployeeRepository();
List<Employee> employees = repository.GetAll();
foreach (Employee employee in employees) { Console.WriteLine($"{employee.EmployeeId}:{employee.EmployeeName}"); }
Employee? foundEmployee = repository.FindById(1002);
if (foundEmployee != null) { Console.WriteLine($"検索結果:{foundEmployee.EmployeeName}"); } }}
interface IEmployeeRepository{ List<Employee> GetAll(); Employee? FindById(int employeeId);}
class SampleEmployeeRepository : IEmployeeRepository{ private List<Employee> _employees = new List<Employee> { new Employee { EmployeeId = 1001, EmployeeName = "山田太郎" }, new Employee { EmployeeId = 1002, EmployeeName = "佐藤花子" }, new Employee { EmployeeId = 1003, EmployeeName = "鈴木一郎" } };
public List<Employee> GetAll() { return _employees; }
public Employee? FindById(int employeeId) { return _employees.FirstOrDefault(employee => employee.EmployeeId == employeeId); }}
class Employee{ public int EmployeeId { get; set; } public string EmployeeName { get; set; } = "";}実行結果:
1001:山田太郎1002:佐藤花子1003:鈴木一郎検索結果:佐藤花子DB接続版に差し替えるイメージ
Section titled “DB接続版に差し替えるイメージ”今は、SampleEmployeeRepository がサンプルデータを返しています。
後のDB接続編では、Oracle Databaseからデータを取得するクラスを作ることになります。
SampleEmployeeRepository → サンプルデータを返す
OracleEmployeeRepository → Oracle Databaseから取得するどちらも IEmployeeRepository を実装していれば、呼び出し側は同じように扱えます。
IEmployeeRepository repository = new SampleEmployeeRepository();将来的には、次のように差し替えるイメージです。
IEmployeeRepository repository = new OracleEmployeeRepository();このように、インターフェイスを使うと、呼び出し側のコードを大きく変えずに実装を差し替えやすくなります。
補足
Webアプリでは、さらにDIという仕組みを使って、インターフェイスと実装クラスを組み合わせることがあります。 この章では深く扱いませんが、
IEmployeeRepositoryのような名前を見たときに「社員データ取得の約束を表しているのだな」と読めることを目指します。
よくあるつまずき
Section titled “よくあるつまずき”この章でよくあるつまずきを確認します。
| つまずき | 原因 | 対応 |
|---|---|---|
| インターフェイスの意味が分からない | 処理の中身がなく抽象的に見える | 「機能の約束」と考える |
interface と class の違いが分からない | どちらも型として使えるため混同する | classは実体を作る設計図、interfaceは約束 |
IPrintable の I が分からない | 命名規則を知らない | InterfaceのIと考える |
| インターフェイスのメソッドに処理を書こうとする | クラスのメソッドと混同している | 本研修ではインターフェイスには中身を書かない |
| 実装クラスでメソッドを書き忘れる | 約束されたメソッドを実装していない | エラー内容を見て不足メソッドを追加する |
| インターフェイス型でプロパティが使えない | インターフェイスに定義されていない | インターフェイス型では約束されたメンバーだけ使える |
| 抽象クラスとの違いが分からない | どちらもポリモーフィズムに使える | 抽象クラスは共通の土台、インターフェイスは機能の約束 |
| インターフェイスをどこで使うのか分からない | 小さなサンプルでは必要性を感じにくい | 現場ではServiceやRepositoryでよく見ると考える |
学んだことチェック
Section titled “学んだことチェック”次の項目について、自分で説明できるか確認してください。
- インターフェイスとは何かをおおまかに説明できる
- インターフェイスは「機能の約束」であることを説明できる
-
interfaceを使ってインターフェイスを定義できる - インターフェイス名に
Iを付ける慣習を説明できる - クラスでインターフェイスを実装できる
- インターフェイスで定義したメソッドをクラス側で実装できる
- インターフェイス型の変数に実装クラスのオブジェクトを代入できる
-
List<IPrintable>のように、インターフェイス型のリストを使える - インターフェイスにプロパティを定義できる
- 1つのクラスが複数のインターフェイスを実装できることを説明できる
- 抽象クラスとインターフェイスの違いをおおまかに説明できる
-
IEmployeeRepositoryのような名前を見たときに、役割を想像できる
研修の進め方によっては、隣の人またはチーム内で説明確認を行います。
次の内容を、自分の言葉で説明してください。
- インターフェイスとは何ですか。
IPrintableはどのような役割を持つインターフェイスですか。class Employee : IPrintableは何を意味していますか。- インターフェイス型の変数では、どのメンバーを使えますか。
List<IPrintable>に異なるクラスのオブジェクトを入れられるのはなぜですか。- 抽象クラスとインターフェイスの違いは何ですか。
IEmployeeRepositoryはどのような役割を持つと考えられますか。
説明するときは、完全な答えでなくても構いません。
自分の言葉で説明しようとすることが大切です。
この章の演習課題に取り組みます。
制限時間は 80分 です。
時間内にすべて完成しなくても構いません。
できたところまでを保存し、Gitに提出してください。
まずは、全員が必須課題に取り組んでください。
課題14-1 IPrintableを実装する
Section titled “課題14-1 IPrintableを実装する”IPrintable インターフェイスを作成し、Employee クラスで実装してください。
仕様:
interface IPrintable{ void Print();}実行結果例:
社員ID:1001氏名:山田太郎部署:営業部条件:
interfaceを使うEmployee : IPrintableと書くEmployeeクラスにPrintメソッドを実装する
課題14-2 インターフェイス型の変数を使う
Section titled “課題14-2 インターフェイス型の変数を使う”課題14-1の Employee オブジェクトを、IPrintable 型の変数に代入し、Print メソッドを呼び出してください。
実行結果例:
社員ID:1001氏名:山田太郎部署:営業部条件:
IPrintable printable = new Employee { ... };のように書くprintable.Print();を呼び出す- インターフェイス型では、インターフェイスに定義されたメソッドだけ使えることを確認する
課題14-3 SalesReportにもIPrintableを実装する
Section titled “課題14-3 SalesReportにもIPrintableを実装する”SalesReport クラスを作成し、IPrintable を実装してください。
プロパティ:
| プロパティ名 | 型 |
|---|---|
ReportDate | DateTime |
TotalAmount | int |
実行結果例:
売上日:2026/05/18売上合計:1200000円条件:
SalesReport : IPrintableと書くPrintメソッドを実装する- 日付は
ToString("yyyy/MM/dd")で表示する
課題14-4 Listでまとめて印刷する
Section titled “課題14-4 Listでまとめて印刷する”Employee と SalesReport を List<IPrintable> に入れ、foreach で Print メソッドを呼び出してください。
条件:
List<IPrintable>を使うEmployeeとSalesReportを同じリストに入れるforeachでPrintを呼び出す- 実際のクラスによって表示内容が変わることを確認する
必須課題が終わった人は、発展課題に取り組んでください。
課題14-5 IPayableを実装する
Section titled “課題14-5 IPayableを実装する”支給額を計算できることを表す IPayable インターフェイスを作成してください。
仕様:
interface IPayable{ int GetPaymentAmount();}RegularEmployee と ContractEmployee に IPayable を実装してください。
| クラス | 支給額 |
|---|---|
RegularEmployee | 月給 |
ContractEmployee | 時給 × 勤務時間 |
実行結果例:
支給額:300000円支給額:216000円条件:
IPayableを作成するRegularEmployee : IPayableとするContractEmployee : IPayableとするList<IPayable>でまとめて処理する
課題14-6 複数のインターフェイスを実装する
Section titled “課題14-6 複数のインターフェイスを実装する”RegularEmployee クラスに、IPrintable と IPayable の両方を実装してください。
実行結果例:
社員ID:1001氏名:山田太郎部署:営業部支給額:300000円条件:
class RegularEmployee : IPrintable, IPayableと書くPrintメソッドを実装するGetPaymentAmountメソッドを実装する
課題14-7 IEmployeeRepositoryを作成する
Section titled “課題14-7 IEmployeeRepositoryを作成する”社員データを取得するための IEmployeeRepository インターフェイスを作成してください。
仕様:
interface IEmployeeRepository{ List<Employee> GetAll(); Employee? FindById(int employeeId);}次に、サンプルデータを返す SampleEmployeeRepository クラスを作成してください。
実行結果例:
1001:山田太郎1002:佐藤花子1003:鈴木一郎検索結果:佐藤花子条件:
IEmployeeRepositoryを作成するSampleEmployeeRepository : IEmployeeRepositoryと書くGetAllで全社員を返すFindByIdで社員ID検索を行うFirstOrDefaultを使ってもよい
課題14-8 Repositoryを差し替えるイメージを確認する
Section titled “課題14-8 Repositoryを差し替えるイメージを確認する”IEmployeeRepository 型の変数に SampleEmployeeRepository を代入して使ってください。
IEmployeeRepository repository = new SampleEmployeeRepository();その後、コメントとして次の内容を書いてください。
// 後のDB接続編では、ここを OracleEmployeeRepository に差し替えるイメージ// IEmployeeRepository repository = new OracleEmployeeRepository();条件:
- インターフェイス型で実装クラスを扱う
- 後のDB接続編で実装を差し替えるイメージをコメントで残す
- 現時点では
OracleEmployeeRepositoryは作成しなくてよい
Gitへの提出
Section titled “Gitへの提出”課題が終わったら、できたところまでをGitに提出します。
まず、現在の状態を確認します。
git status変更されたファイルを追加します。
git add .コミットします。
git commit -m "Chapter14 インターフェイス"ファイルサーバー上のリポジトリへpushします。
git pushGitの操作でエラーが出た場合は、自己判断で同じ操作を繰り返さず、講師に確認してください。
提出前チェックリスト
Section titled “提出前チェックリスト”提出前に、次の項目を確認してください。
-
interfaceを使ってインターフェイスを作成できている - インターフェイス名の先頭に
Iを付けている - クラスでインターフェイスを実装できている
- インターフェイスで定義したメソッドをクラス側で実装している
- インターフェイス型の変数を使えている
-
List<インターフェイス>を使えている - 複数のクラスを同じインターフェイスで扱えている
- 複数のインターフェイスを実装できている
- 抽象クラスとインターフェイスの違いをおおまかに説明できる
-
IEmployeeRepositoryの役割を説明できる - インデントが整っている
- Gitにcommitしている
- Gitにpushしている
この章のまとめ
Section titled “この章のまとめ”この章では、インターフェイスについて学習しました。
この章で学んだ主な内容は次の通りです。
- インターフェイスは、クラスが持つべき機能の約束を表す
- インターフェイスは
interfaceキーワードで定義する - C#では、インターフェイス名の先頭に
Iを付けることが多い - インターフェイスには、メソッドやプロパティを定義できる
- 本研修では、インターフェイスには処理の中身を書かず、約束だけを書くものとして扱う
- クラスは、インターフェイスを実装することで、その機能を持つことを示す
- インターフェイスを実装したクラスは、約束されたメンバーを実装する必要がある
- インターフェイス型の変数には、実装クラスのオブジェクトを代入できる
List<IPrintable>のように、異なるクラスを同じインターフェイスでまとめて扱える- 1つのクラスは、複数のインターフェイスを実装できる
- 抽象クラスは共通の土台、インターフェイスは機能の約束として考えると分かりやすい
IEmployeeRepositoryのようなインターフェイスは、後のDB接続やWebアプリで実装を差し替える考え方につながる
次章では、例外処理 を学習します。
プログラムでは、入力ミス、ファイルが存在しない、DB接続に失敗するなど、さまざまなエラーが発生します。
例外処理を学ぶことで、エラーが発生したときにプログラムを安全に扱う方法を身に付けます。