C#

【C#】インタフェースとは?具体的にどんなものなのかを説明する【オブジェクト指向】

今回はオブジェクト指向のプログラミングをするにあたり、C#プログラミングでは必須の「インタフェース」について説明します。
「インタフェース」を正しく理解していますか?

皆さんはC#でプログラミングするときにインタフェースを使った実装をしているでしょうか?

オブジェクト指向を理解するためには、前回のカプセル化のほかに、インタフェースを使い効率よくプログラミングする必要があります!
インタフェースを利用すると、同じコードを書かなくなり処理が冗長になりにくいので、必ず理解するようにしてください。

今回は普段より筋トレが好きなので”ジム会員の割引”を例に「インタフェース」を使ったプログラムを実装し、説明していきます。

インタフェースとは?

インタフェースとは、「クラスでどんな処理を行う必要があるか」ということを、具体的な処理は記載せず「形」というモデルを意味します。。。
といっても文字で説明するのはクソむずいので…今回も実装して説明します!!

クッキーとかケーキを作るときの形みたいな…やつ!

アプリケーションを作成して解説します!

プロジェクトを作成しよう!

まず、Visual Studioを起動しましょう。
今回、エリ狐はVisual Studio 2019を使用しますが、2017でも2015でも可です。
プロジェクト作成
図のように「Windowsフォームアプリケーション(.NETFrameWork)」を選択し「次へ」を押下します。

プロジェクト名称は適当で大丈夫です。
私は「Interface」というプロジェクト名にして、作成しました。

すると、Form1.cs[デザイン]が表示されるので以下のプロパティ設定をしてください。

Form1のサイズ size: 300, 300
radioButtonの追加 3つのラジオボタンを追加します。
◆フリー会員ボタン
(Name):FreePlanButton
Text: フリー会員
◆週2会員ボタン
(Name):TwoWeekPlanButton
Text: 週2会員
◆週1会員ボタン
(Name):OneWeekPlanButton
Text: 週1会員
TextBoxの追加 (Name):PriceTextBox
Buttonの追加 (Name):AnsButton
Text: 小計
Labelの追加 (Name):PriceLabel
Text: 0 円

プロジェクトフォーム
このようにラベルとボタンを配置してください。

次にボタンクリック時のイベント処理を追加します。
「Form1」に配置したボタンをダブルクリックするとボタンのクリックイベントが自動的に生成されます。
クリックイベント追加

赤枠の処理が追加されたらOKです。
この枠で囲った処理は、処理名称(メソッド名)の通り、「AnsButton_Click」ボタンをクリックすると起動されます。

処理を書いていく

今回は、それぞれジムの会員区分によって小計の割引率が異なる仕様で作成していきます。

  • フリー会員:割引率35%
  • 週2会員 :割引率15%
  • 週1会員 :割引率5%

インタフェースを使用しないで処理を書くと…

まずは、インタフェースを利用しない場合のコードを見ていきましょう。
おそらく、このような仕様を普通に次のように実装するでしょう。(多少は異なるかもですが、大体は同じ感じになりそう。

using System;
using System.Windows.Forms;

namespace Interface
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void AnsButton_Click(object sender, EventArgs e)
        {
            //フリー会員:割引率35 %
            //週2会員   :割引率15 %
            //週1会員   :割引率5 %

            //テキストボックスより小計額を取得
            var SumPrice = Convert.ToInt32(PriceTextBox.Text);

            //週1会員 選択
            if (OneWeekPlanButton.Checked) 
            {
                //5%割引した値を設定する
                PriceLabel.Text = (SumPrice * 0.95).ToString() + " 円";
            }

            //週2会員 選択
            if (TwoWeekPlanButton.Checked)
            {
                //15%割引した値を設定する
                PriceLabel.Text = (SumPrice * 0.85).ToString() + " 円";
            }

            //フリー会員 選択
            if (FreePlanButton.Checked)
            {
                //35%割引した値を設定する
                PriceLabel.Text = (SumPrice * 0.65).ToString() + " 円";
            }

            return;
        }
    }
}

今回は、このコードにインタフェースを実装するとどのようになるのかを見ていきます。

インタフェースを使った実装をする!

インタフェースを実装するために、クラスを用意します。
クラスの追加
[プロジェクト]-[追加]-[クラス]よりクラスファイルを作成します。
今回は「IGYMMember.cs」という名前で作成します。
インタフェースの作成
追加したら、アクセス修飾子を「Public」Classを「interface」に変更します。

先頭に”I”をつける理由はMicrosoftの命名規約によるものです!

Microsoftのインタフェースを見てみると頭にIが必ずついています。
「絶対つけなきゃダメ」というわけではないですが、私の経験上はどこの現場のプログラムソースを見てもIから始まっているので、つかるのが”無難”です。


割引率のプロパティを用意します。
今回は「DiscountRate」という名前で用意しました。

インタフェースはこのようにプロパティを定義します。

このようにインタフェースを用意したら、このインタフェース利用するクラスを作成していきます。
今回は会員ごとに割引率を変化させたいので、「フリー会員」、「週2会員」、「週1会員」ごとのクラスを用意します。

sealed 修飾子をクラスに付けると、それ以外のクラスが、そのクラスから継承できなくなります。
例えばクラスAとBがあり、Bクラスにsealedを付与すると場合…BクラスはAクラスを継承できるが、AクラスからはAクラスも継承できなくなるということです。

一方通行ってやつですな!

クラスを実装すると…画像のようにインタフェースに赤い波線が引かれます。
これは、先ほど追加した「DiscountRate」をクラス内に実装していないためです。

これをわざわざ自分の手で作らなくても、波線にフォーカスを当て「ctrl + .(ドット)」で実装できます!(小技)

このように、自分でガリガリ書くよりも自動で作成したほうがミスが減るのでお勧めです。
■IGYMMember.cs

namespace Interface
{
    public interface IGYMMember
    {
        //値引き率のプロパティを定義
         float DiscountRate { get;}
    }

    public sealed class FreeMember : IGYMMember
    {
        public float DiscountRate => 0.65f;
    }

    public sealed class TwoWeekMember : IGYMMember
    {
        public float DiscountRate => 0.85f;
    }

    public sealed class OneWeekMember : IGYMMember
    {
        public float DiscountRate => 0.95f;
    }
}

これを実装したら、Form1.csを修正します。
先ほど、ラジオボタンの選択によって、Form1に割引率を定義していましたが、インタフェースより取得するように変更しました。
■Form1.cs

using System;
using System.Windows.Forms;

namespace Interface
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void AnsButton_Click(object sender, EventArgs e)
        {
            //フリー会員:割引率35 %
            //週2会員   :割引率15 %
            //週1会員   :割引率5 %

            //テキストボックスより小計額を取得
            var SumPrice = Convert.ToInt32(PriceTextBox.Text);

            //インタフェースを準備
            IGYMMember gymMember;

            if (OneWeekPlanButton.Checked)
            {
                //週1会員 選択
                //5%割引した値を設定する
                gymMember = new OneWeekMember();
            }         
            else if (TwoWeekPlanButton.Checked)     
            {
                //週2会員 選択
                //15%割引した値を設定する
                gymMember = new TwoWeekMember();
            }
            else       
            {
                //フリー会員 選択
                //35%割引した値を設定する
                gymMember = new FreeMember();
            }

            PriceLabel.Text = (SumPrice * gymMember.DiscountRate).ToString() + " 円";
            return;
        }
    }
}

インタフェースを使用することにより、それぞれのクラスをnewするだけで割引率が取得できるようになりました。

実行すると正しく動作していることが分かります。
いかがでしょうか。インタフェースを利用するとnewしたクラスごとに値を変化するため処理が冗長にならないというメリットがあります!

しかし、ちょっとメリットについていまいちピンときていない方もいらっしゃるとおもうので、また別の機会に違った例で説明しますのでお楽しみに!